module klang.ir.检查.IR检查_;
import 全局;
import std.conv: ·to = to;
import std.functional: ·fd = toDelegate;
import ··Align_ = klang.编译.Align.Align_;
import ··IR节点_ = klang.ir.语法节点.IR节点_;
import 基础节点 = klang.编译.语法节点.节点_;
import 编译数字 = 编译数字.编译;
import klang.编译.APSInt.APSInt_: APSInt_, APSInt_isSameValue = isSameValue;
import klang.编译.APInt.APInt_: APInt_, APInt_getZero = getZero, APInt_getAllOnesValue = getAllOnesValue, APInt_isSameValue = isSameValue, APInt_getLowBitsSet = getLowBitsSet, PowerOf2Ceil, isPowerOf2_64, UINT32_MAX;
import klang.编译.APFloat.APFoat_: APFloat_, IEEEFloat_, DoubleAPFloat_, RoundingMode_, rmNearestTiesToEven, rmTowardZero, APFloat_CmpResult_ = CmpResult_, APFloat_OpStatus_ = OpStatus_, APFloat_getAllOnesValue, APFloat_getInf, APFloat_getNaN, APFloat_getQNaN, APFloat_getSNaN, APFloat_getZero, FltSemantics_, IEEEhalf, BFloat, IEEEsingle, IEEEdouble, IEEEquad, x87DoubleExtended, Bogus, PPCDoubleDouble;
import klang.编译.语法节点.节点_: 基础节点_ = 节点_, 节点数组_, 基础源文件_ = 源文件_, 创建基础节点 = 创建节点, 基础标识符_ = 标识符_, nodeIsSynthesized, 查找祖先;
import klang.编译.工具.工具_: 诊断收集_, 创建符号表, 创建编译诊断, 创建节点的诊断, 获取节点的源文件, 获取节点的文本, addRelatedInfo, 创建文件诊断消息, getParseTreeNode_1, 比较诊断;
import klang.编译.路径.路径_: 正规化路径, 获取目录路径, 比较路径;
import klang.编译.类型.枚举值.枚举值_: SK, TK, 字符_, 比较结果_;
import klang.编译.诊断集.诊断集_: 诊断集_;
import klang.编译.triple.Triple: Triple, 编译目标平台内容;
import klang.编译.Align.Align_: Align_, Dims_, LogValue_, TypeSize, Fixed, ElementCount, ECFixed;
import klang.编译.诊断.诊断_: 诊断_, 诊断消息_, 诊断相关信息_, 诊断包括位置_, 诊断消息链_ = 诊断消息_链_, concatenateDiagnosticMessageChains;
import klang.编译.类型.类型_: 基础符号_ = 符号_, 符号表_, 解析的模块名称_, 语法系统_, 基础类型_ = 类型_, 流节点_, 流标志_, 检查源文件函数_, 取消令牌_, 程序主机接口_, 编译选项基类_, 转换支持_, 打印助手_, EmitHint, IEmitTextWriter, 三元结果_;
import klang.编译.核心.核心_: 整数_, 每个, 部分, 过滤, 词典_, 映射, 查找, 连接, 不改变, 扁平化, sameMap, 创建数组, 返回零值, 循环每个, 二分搜索, 扁平化映射, reduceLeft, 比较器比较值, rangeEquals, pushIfUnique, appendIfUnique, orderedRemoveItemAt, arrayIsHomogeneous, getOrUpdate, 按字符分割, 结尾包含, 映射定义的, 每个数组成员;
import klang.编译.输出工具.输出工具_: 创建文本写;
import 核心 = klang.编译.核心.核心_;
import klang.编译.dataLayout.DataLayout: DataLayout, parseSpecifier, FunctionPtrAlignType, isAligned, alignTo, alignTo_1, AlignTypeEnum, LayoutAlignElem;
import klang.编译.输出节点.输出节点_: setEmitFlags, EmitFlags, setTextRange, setOriginalNode;
import klang.ir.节点工厂.IR工厂_: IR工厂_, 节点工厂标志_;
import klang.ir.内联汇编.InlineAsm: InlineAsm_Verify = Verify;
import klang.ir.类型.IR类型_: ISK, 编译选项_, 节点标志_, 类型标志_, TypeID_, 类型_ = IR类型_, 符号_ = IR符号_, 指针类型_, 结构类型_, 向量类型_, 数组类型_, 函数类型_, 符号标志_, 整数类型_, ValueField_, ValueTy_, Value, SValue, Constant, ConstantInt, ConstantFP, ConstantPointerNull, UndefValue, PoisonValue, ConstantAggregateZero, ConstantAggregate, ConstantTokenNone, ConstantStruct, ConstantDataSequential, ConstantDataArray, ConstantDataVector, ConstantArray, ConstantVector, GlobalObject, Module, GlobalVariable, Argument, BlockAddress, DSOLocalEquivalent, InlineAsm, AsmDialect, GlobalValue, Function, BasicBlock, ConstantExpr, ShuffleVectorConstantExpr, ExtractValueConstantExpr, InsertValueConstantExpr, GetElementPtrConstantExpr, CompareConstantExpr, UnaryConstantExpr, BinaryConstantExpr, SelectConstantExpr, ExtractElementConstantExpr, InsertElementConstantExpr, InstructionKind_, CmpInst_Predicate_, PossiblyExactOperator_, OverflowingBinaryOperator_, 常量元素组_, 特性组值_, 封装值_, 特性种类_, 特性组_, 特性_, 枚举特性_, 整数特性_, 文本特性_, 类型特性_, 对齐特性_, 对齐值_ = 对齐设置_, 地址值_ = 地址空间设置_, 同步值_ = 同步范围设置_, 三点值_, 元数据值_, 函数体, Instruction, UnreachableInst, RetInst, BranchInst, 跳转表_, SwitchInst, IndirectBrInst, InvokeInst, ResumeInst, CleanupReturnInst, CatchReturnInst, CatchSwitchInst, CleanupPadInst, CatchPadInst, CallBrInst, UnaryOperator, FNegInst, BinaryOperator, AddInst, FAddInst, SubInst, FSubInst, MulInst, FMulInst, UDivInst, SDivInst, FDivInst, URemInst, SRemInst, FRemInst, ShlInst, LShrInst, AShrInst, AndInst, OrInst, XorInst, AllocaInst, LoadInst, AtomicCmpXchgInst, AtomicRMWInst, FenceInst, GetElementPtrInst, ExtractValueInst, InsertValueInst, GlobalAlias, GlobalIFunc, CallBase, TruncInst, ZExtInst, SExtInst, FPTruncInst, FPExtInst, BitCastInst, AddrSpaceCastInst, UIToFPInst, SIToFPInst, FPToUIInst, FPToSIInst, IntToPtrInst, PtrToIntInst, CmpInst, ICmpInst, FCmpInst, ParamInfo, BundleDef, BundleDefS, VAArgInst, ExtractElementInst, InsertElementInst, ShuffleVectorInst, PHINode, LandingPadInst, FreezeInst, CallInst, LinkageTypes, VisibilityTypes, DLLStorageClassTypes, AttrKind_, UnnamedAddr, SelectionKind, AtomicOrdering_, FastMathFlags_, CallingConv_, TailCallKind_, AtomicRMWInstBinOp_, ThreadLocalMode_, 标识符分类_;
import klang.ir.语法节点.IR节点_: 源文件_ = IR源文件_, 节点_ = IR节点_, 标识符_, IR文本字面量_, IR数字字面量_, 类型声明_, 函数定义_, 函数声明_, 全局变量声明_, 别名声明_, 封装声明_, 独立元数据_, 元数据声明_, 特性声明_, 全局摘要声明_, 模块级汇编_, 形参声明_, 局部变量声明_, 块声明_, 值表达式_, 整数类型节点_ = 整数类型_, 结构类型节点_ = 结构类型_, 向量类型节点_ = 向量类型_, 数组类型节点_ = 数组类型_, 指针类型节点_ = 指针类型_, 函数类型节点_ = 函数类型_, 类型引用_, 本地线程设置_, 全局声明_, 全局值声明_, 函数基类_, 全局表达式_, 不透明指针类型_, 自定义特性设置_, 不可引用的设置_, 不可引用的或空设置_, 对齐设置_, 对齐堆栈设置_, 倍数范围设置_, 预分配设置_, 按引用设置_, 在内部分配设置_, 结构引用设置_, 按值设置_, 分配大小设置内容_, 倍数范围设置内容_, 分配大小设置_, 地址空间设置_, 设置型节点_, 封装设置_, c文本常量_, 内联汇编常量表达式_, 提取值常量表达式_, 插入值常量表达式_, 比较类常量表达式_, 取反常量表达式_, 二元常量表达式_, 逻辑类常量表达式_, 获取元素指针常量表达式_, 向量洗牌常量表达式_, 插入元素常量表达式_, 提取元素常量表达式_, 选择常量表达式_, 结构常量表达式_, 向量常量表达式_, 数组常量表达式_, 块地址表常量表达式_, DSO局部等效常量表达式_, 常量转换类节点_, 函数体_, 目标语句_, 平台设置_, 数据布局设置_, 同步范围设置_, 调用基类_, 实参表达式_, CC调用约定设置_, 操作数标签组_, 用户历史数据_, 不及指令_, 返回指令_, 跳转指令_, 假如指令_, 直接跳转指令_, 唤出指令_, 重启指令_, 清理返回指令_, 捕获返回指令_, 捕获分支指令_, 清理场指令_, 捕获场指令_, 调用跳转指令_, 可变参数指令_, 提取元素指令_, 插入元素指令_, 洗牌向量指令_, PHI节点指令_, PHI节点元素_, 取反指令_, 整数和差积及左移指令_, 小数和差积及左移指令_, 有无符号求商及右移指令_, 有无符号求余数运算指令_, 位运算指令_, 比较运算指令_, 转换类指令_, 是IR节点, 获取IR节点, 遍历节点, 是局部声明语句, 冻结指令_, 分配指令_, 加载指令_, 储存指令_, 捕获或过滤器_, 着陆场指令_, 调用指令_, 原子修改内存按条件指令_, 原子修改内存指令_, 栅格指令_, 获取元素指针指令_, 提取值指令_, 插入值指令_, 跳转表元素_;
import klang.ir.工具.IR工具_: 获取连接类型, 获取链接特性的令牌, ISK转为AtomicRMWInstBinOp, ISK转为CastOpc, ISK转为CmpInst_Predicate, ISK转为比较运算符, ISK转为二元运算指令, ISK转为快速数学标志, ISK转为逻辑运算指令, ISK转换调用约定, ISK转尾调用标志, ISK转AtomicOrdering, getAtomicRMWInstBinOpName;
import klang.ir.常量值.IR常量值_: 获取ISK关键字文本;
alias 获取符号_ = 符号_ delegate(符号表_, dstring, 符号标志_);
long 下个Id = 1;
long 合并Id = 1;
long 流Id = 1;
long 符号数量 = 0;
long 类型数量 = 0;
诊断收集_ 诊断集;
源文件_ 当前源文件;
long NumberedTypes = 0;
long NumberedVals = 0;
long NumberedAttrBuilders = 0;
语法系统_[] resolutionTargets;
bool[] resolutionResults;
klang.ir.检查.IR检查_.类型系统名称_[] resolutionPropertyNames;
bool 报告错误;
程序主机接口_ 当前主机;
编译选项_ 当前编译选项;
Triple 目标平台;
DataLayout 当前布局;
IR工厂_ factory;
词典_!(klang.ir.检查.IR检查_.DuplicateInfoForFiles) amalgamatedDuplicates;
词典_!(指针类型_) PointerTypes;
词典_!(指针类型_) ASPointerTypes;
词典_!(结构类型_) AnonStructTypes;
词典_!(结构类型_) NamedStructTypes;
词典_!(向量类型_) VectorTypes;
词典_!(数组类型_) ArrayTypes;
词典_!(函数类型_) FunctionTypes;
词典_!(ubyte) SSC;
词典_!(dstring) GCNames;
词典_!(整数类型_) 整数类型集合;
词典_!(klang.ir.检查.IR检查_.StructLayout) LayoutMap;
uint MaxAlignmentExponent = 29;
uint MaximumAlignment;
词典_!(ulong) CustomMDKindNames;
类型_ VoidTy;
类型_ LabelTy;
类型_ HalfTy;
类型_ BFloatTy;
类型_ FloatTy;
类型_ DoubleTy;
类型_ MetadataTy;
类型_ TokenTy;
类型_ X86_FP80Ty;
类型_ FP128Ty;
类型_ PPC_FP128Ty;
类型_ X86_MMXTy;
类型_ X86_AMXTy;
结构类型_ 不透明结构类型;
整数类型_ Int1Ty;
整数类型_ Int8Ty;
整数类型_ Int16Ty;
整数类型_ Int32Ty;
整数类型_ Int64Ty;
整数类型_ Int128Ty;
Constant TheTrueVal;
Constant TheFalseVal;
词典_!(ConstantTokenNone) TheNoneToken;
词典_!(ConstantPointerNull) CPNConstants;
词典_!(UndefValue) UVConstants;
词典_!(PoisonValue) PVConstants;
词典_!(ConstantInt) IntConstants;
词典_!(ConstantFP) FPConstants;
词典_!(ConstantAggregateZero) CAZConstants;
词典_!(ConstantDataSequential) CDSConstants;
词典_!(ConstantStruct) StructConstants;
词典_!(ConstantVector) VectorConstants;
词典_!(ConstantArray) ArrayConstants;
词典_!(BlockAddress) BlockAddresses;
词典_!(DSOLocalEquivalent) DSOLocalEquivalents;
词典_!(ConstantExpr) ExprConstants;
词典_!(InlineAsm) InlineAsms;
类型_ 未知类型;
long[] 特性属性表;
static this() {
    resolutionTargets = 创建数组!(语法系统_)();
    resolutionResults = 创建数组!(bool)();
    resolutionPropertyNames = 创建数组!(klang.ir.检查.IR检查_.类型系统名称_)();
    PointerTypes = new 词典_!(指针类型_)();
    ASPointerTypes = new 词典_!(指针类型_)();
    AnonStructTypes = new 词典_!(结构类型_)();
    NamedStructTypes = new 词典_!(结构类型_)();
    VectorTypes = new 词典_!(向量类型_)();
    ArrayTypes = new 词典_!(数组类型_)();
    FunctionTypes = new 词典_!(函数类型_)();
    SSC = new 词典_!(ubyte)();
    GCNames = new 词典_!(dstring)();
    整数类型集合 = new 词典_!(整数类型_)();
    LayoutMap = new 词典_!(klang.ir.检查.IR检查_.StructLayout)();
    MaximumAlignment = 1 << .MaxAlignmentExponent;
    CustomMDKindNames = new 词典_!(ulong)();
    VoidTy = .创建内置类型(TypeID_.VoidTyID);
    LabelTy = .创建内置类型(TypeID_.LabelTyID);
    HalfTy = .创建内置类型(TypeID_.HalfTyID);
    BFloatTy = .创建内置类型(TypeID_.BFloatTyID);
    FloatTy = .创建内置类型(TypeID_.FloatTyID);
    DoubleTy = .创建内置类型(TypeID_.DoubleTyID);
    MetadataTy = .创建内置类型(TypeID_.MetadataTyID);
    TokenTy = .创建内置类型(TypeID_.TokenTyID);
    X86_FP80Ty = .创建内置类型(TypeID_.X86_FP80TyID);
    FP128Ty = .创建内置类型(TypeID_.FP128TyID);
    PPC_FP128Ty = .创建内置类型(TypeID_.PPC_FP128TyID);
    X86_MMXTy = .创建内置类型(TypeID_.X86_MMXTyID);
    X86_AMXTy = .创建内置类型(TypeID_.X86_AMXTyID);
    不透明结构类型 = new 结构类型_(返回零值!(符号_)());
    Int1Ty = TGet_.s·IntTy_get(1);
    Int8Ty = TGet_.s·IntTy_get(8);
    Int16Ty = TGet_.s·IntTy_get(16);
    Int32Ty = TGet_.s·IntTy_get(32);
    Int64Ty = TGet_.s·IntTy_get(64);
    Int128Ty = TGet_.s·IntTy_get(128);
    TheNoneToken = new 词典_!(ConstantTokenNone)();
    CPNConstants = new 词典_!(ConstantPointerNull)();
    UVConstants = new 词典_!(UndefValue)();
    PVConstants = new 词典_!(PoisonValue)();
    IntConstants = new 词典_!(ConstantInt)();
    FPConstants = new 词典_!(ConstantFP)();
    CAZConstants = new 词典_!(ConstantAggregateZero)();
    CDSConstants = new 词典_!(ConstantDataSequential)();
    StructConstants = new 词典_!(ConstantStruct)();
    VectorConstants = new 词典_!(ConstantVector)();
    ArrayConstants = new 词典_!(ConstantArray)();
    BlockAddresses = new 词典_!(BlockAddress)();
    DSOLocalEquivalents = new 词典_!(DSOLocalEquivalent)();
    ExprConstants = new 词典_!(ConstantExpr)();
    InlineAsms = new 词典_!(InlineAsm)();
    未知类型 = .创建内置类型(TypeID_.未知类型_);
    特性属性表 = [
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.ParamAttr)),
        (cast(整数_)(特性属性_.ParamAttr | 特性属性_.RetAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.ParamAttr)),
        (cast(整数_)(特性属性_.ParamAttr | 特性属性_.RetAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.ParamAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr | 特性属性_.ParamAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.ParamAttr | 特性属性_.RetAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.ParamAttr | 特性属性_.RetAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr | 特性属性_.ParamAttr)),
        (cast(整数_)(特性属性_.FnAttr | 特性属性_.ParamAttr)),
        (cast(整数_)(特性属性_.ParamAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.ParamAttr | 特性属性_.RetAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.ParamAttr)),
        (cast(整数_)(特性属性_.ParamAttr)),
        (cast(整数_)(特性属性_.ParamAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.FnAttr | 特性属性_.ParamAttr)),
        (cast(整数_)(特性属性_.ParamAttr | 特性属性_.RetAttr)),
        (cast(整数_)(特性属性_.ParamAttr)),
        (cast(整数_)(特性属性_.ParamAttr)),
        (cast(整数_)(特性属性_.ParamAttr)),
        (cast(整数_)(特性属性_.ParamAttr)),
        (cast(整数_)(特性属性_.FnAttr | 特性属性_.ParamAttr)),
        (cast(整数_)(特性属性_.ParamAttr)),
        (cast(整数_)(特性属性_.ParamAttr | 特性属性_.RetAttr)),
        (cast(整数_)(特性属性_.FnAttr)),
        (cast(整数_)(特性属性_.ParamAttr | 特性属性_.RetAttr)),
        (cast(整数_)(特性属性_.ParamAttr | 特性属性_.RetAttr)),
        (cast(整数_)(特性属性_.FnAttr | 特性属性_.ParamAttr)),
        (cast(整数_)(特性属性_.FnAttr))
    ];
}
enum 类型系统名称_ : int {
    类型_ = 0,
    声明类型_ = 1
}
enum 特性属性_ : int {
    无_ = 0,
    FnAttr = 1,
    ParamAttr = 2,
    RetAttr = 4
}
class CAZero_ {
    this() { }
    static Constant s·getSequentialElement(类型_ Ty) {
        数组类型_ AT = (cast(数组类型_)(Ty));
        if (AT !is ··null!(数组类型_)) {
            return CGet_.s·getNullValue(AT.元素类型);
        }
        return CGet_.s·getNullValue((cast(向量类型_)(Ty)).元素类型);
    }
    static Constant s·getStructElement(结构类型_ ST, uint Elt) {
        return CGet_.s·getNullValue(.getStructElementType(ST, Elt));
    }
    static Constant s·getElementValue(类型_ Ty, Constant C) {
        if (Ty.种类 == TypeID_.ArrayTyID || Ty.种类 == TypeID_.FixedVectorTyID || Ty.种类 == TypeID_.ScalableVectorTyID) {
            return CAZero_.s·getSequentialElement(Ty);
        }
        return CAZero_.s·getStructElement((cast(结构类型_)(Ty)), (cast(uint)((cast(ConstantInt)(C)).Val.getZExtValue())));
    }
    static Constant s·getElementValue(类型_ Ty, uint Idx) {
        if (Ty.种类 == TypeID_.ArrayTyID || Ty.种类 == TypeID_.FixedVectorTyID || Ty.种类 == TypeID_.ScalableVectorTyID) {
            return CAZero_.s·getSequentialElement(Ty);
        }
        return CAZero_.s·getStructElement((cast(结构类型_)(Ty)), Idx);
    }
}
class CDS_ {
    this() { }
    static Constant s·getElementAsConstant(ConstantDataSequential C, uint Elt) {
        bool delegate(类型_) 是浮点;
        bool 是浮点·func(类型_ t) {
            return t.种类 == TypeID_.HalfTyID || t.种类 == TypeID_.BFloatTyID || t.种类 == TypeID_.FloatTyID || t.种类 == TypeID_.DoubleTyID;
        }
        是浮点 = &是浮点·func;
        if (是浮点(C.类型)) {
            return CGet_.s·CFP_get(CDS_.s·getElementAsAPFloat(C, Elt));
        }
        return CGet_.s·CInt_get(C.类型, CDS_.s·getElementAsInteger(C, Elt), false);
    }
    static ulong s·getNumElements(ConstantDataSequential V) {
        数组类型_ AT = (cast(数组类型_)(V.类型));
        if (AT !is ··null!(数组类型_)) {
            return AT.数量;
        }
        return (cast(向量类型_)(V.类型)).数量;
    }
    static uint s·getElementCount(类型_ Ty) {
        数组类型_ AT = (cast(数组类型_)(Ty));
        if (AT !is ··null!(数组类型_)) {
            return (cast(uint)(AT.数量));
        }
        return (cast(uint)((cast(向量类型_)(Ty)).数量));
    }
    static ulong s·getElementByteSize(ConstantDataSequential C) {
        return .getPrimitiveSizeInBits(C.类型).getFixedSize() / 8;
    }
    static char[] s·getElementPointer(ConstantDataSequential C, uint Elt) {
        assert(Elt < CDS_.s·getElementByteSize(C), "Invalid Elt"c);
        return C.DataElements[Elt * CDS_.s·getElementByteSize(C) .. $];
    }
    static APFloat_ s·getElementAsAPFloat(ConstantDataSequential C, uint Elt) {
        char[] EltPtr = CDS_.s·getElementPointer(C, Elt);
        switch (C.类型.种类) {
            case TypeID_.HalfTyID: {
                ushort[] EltVal = (cast(ushort[])((cast(byte[])(EltPtr))));
                return new APFloat_(IEEEhalf(), new APInt_(16, (cast(ulong)(EltVal[0]))));
            }
            case TypeID_.BFloatTyID: {
                ushort[] EltVal = (cast(ushort[])((cast(byte[])(EltPtr))));
                return new APFloat_(BFloat(), new APInt_(16, (cast(ulong)(EltVal[0]))));
            }
            case TypeID_.FloatTyID: {
                uint[] EltVal = (cast(uint[])((cast(byte[])(EltPtr))));
                return new APFloat_(IEEEsingle(), new APInt_(32, (cast(ulong)(EltVal[0]))));
            }
            case TypeID_.DoubleTyID: {
                ulong[] EltVal = (cast(ulong[])((cast(byte[])(EltPtr))));
                return new APFloat_(IEEEsingle(), new APInt_(64, EltVal[0]));
            }
            default: {
                assert(false, "xxx"c);
                break;
            }
        }
        return 返回零值!(APFloat_)();
    }
    static APInt_ s·getElementAsAPInt(ConstantDataSequential C, uint Elt) {
        char[] EltPtr = CDS_.s·getElementPointer(C, Elt);
        uint 位数 = (cast(整数类型_)(C.类型)).位数;
        switch (位数) {
            case 8: {
                ubyte[] EltVal = (cast(ubyte[])((cast(byte[])(EltPtr))));
                return new APInt_(8, (cast(ulong)(EltVal[0])));
            }
            case 16: {
                ushort[] EltVal = (cast(ushort[])((cast(byte[])(EltPtr))));
                return new APInt_(16, (cast(ulong)(EltVal[0])));
            }
            case 32: {
                uint[] EltVal = (cast(uint[])((cast(byte[])(EltPtr))));
                return new APInt_(32, (cast(ulong)(EltVal[0])));
            }
            case 64: {
                ulong[] EltVal = (cast(ulong[])((cast(byte[])(EltPtr))));
                return new APInt_(64, (cast(ulong)(EltVal[0])));
            }
            default: {
                assert(false, "xxx"c);
                break;
            }
        }
        return 返回零值!(APInt_)();
    }
    static ulong s·getElementAsInteger(ConstantDataSequential C, uint Elt) {
        char[] EltPtr = CDS_.s·getElementPointer(C, Elt);
        uint 位数 = (cast(整数类型_)(C.类型)).位数;
        switch (位数) {
            case 8: {
                ubyte[] EltVal = (cast(ubyte[])((cast(byte[])(EltPtr))));
                return (cast(ulong)(EltVal[0]));
            }
            case 16: {
                ushort[] EltVal = (cast(ushort[])((cast(byte[])(EltPtr))));
                return (cast(ulong)(EltVal[0]));
            }
            case 32: {
                uint[] EltVal = (cast(uint[])((cast(byte[])(EltPtr))));
                return (cast(ulong)(EltVal[0]));
            }
            case 64: {
                ulong[] EltVal = (cast(ulong[])((cast(byte[])(EltPtr))));
                return (cast(ulong)(EltVal[0]));
            }
            default: {
                assert(false, "xxx"c);
                break;
            }
        }
        return 0;
    }
}
class PoV_ {
    this() { }
    static Constant s·getSequentialElement(类型_ Ty) {
        数组类型_ AT = (cast(数组类型_)(Ty));
        if (AT !is ··null!(数组类型_)) {
            return CGet_.s·PoisonValue_get(AT.元素类型);
        }
        return CGet_.s·PoisonValue_get((cast(向量类型_)(Ty)).元素类型);
    }
    static Constant s·getStructElement(结构类型_ ST, uint Elt) {
        return CGet_.s·PoisonValue_get(.getStructElementType(ST, Elt));
    }
    static Constant s·getElementValue_0(类型_ Ty, Constant C) {
        if (Ty.种类 == TypeID_.ArrayTyID || Ty.种类 == TypeID_.FixedVectorTyID || Ty.种类 == TypeID_.ScalableVectorTyID) {
            return PoV_.s·getSequentialElement(Ty);
        }
        return PoV_.s·getStructElement((cast(结构类型_)(Ty)), (cast(uint)((cast(ConstantInt)(C)).Val.getZExtValue())));
    }
    static Constant s·getElementValue_1(类型_ Ty, uint Idx) {
        if (Ty.种类 == TypeID_.ArrayTyID || Ty.种类 == TypeID_.FixedVectorTyID || Ty.种类 == TypeID_.ScalableVectorTyID) {
            return PoV_.s·getSequentialElement(Ty);
        }
        return PoV_.s·getStructElement((cast(结构类型_)(Ty)), Idx);
    }
}
class UnV_ {
    this() { }
    static Constant s·getSequentialElement(类型_ Ty) {
        数组类型_ AT = (cast(数组类型_)(Ty));
        if (AT !is ··null!(数组类型_)) {
            return CGet_.s·UndefValue_get(AT.元素类型);
        }
        return CGet_.s·UndefValue_get((cast(向量类型_)(Ty)).元素类型);
    }
    static Constant s·getStructElement(结构类型_ ST, uint Elt) {
        return CGet_.s·UndefValue_get(.getStructElementType(ST, Elt));
    }
    static Constant s·getElementValue(类型_ Ty, Constant C) {
        if (Ty.种类 == TypeID_.ArrayTyID || Ty.种类 == TypeID_.FixedVectorTyID || Ty.种类 == TypeID_.ScalableVectorTyID) {
            return UnV_.s·getSequentialElement(Ty);
        }
        return UnV_.s·getStructElement((cast(结构类型_)(Ty)), (cast(uint)((cast(ConstantInt)(C)).Val.getZExtValue())));
    }
    static Constant s·getElementValue(类型_ Ty, uint Idx) {
        if (Ty.种类 == TypeID_.ArrayTyID || Ty.种类 == TypeID_.FixedVectorTyID || Ty.种类 == TypeID_.ScalableVectorTyID) {
            return UnV_.s·getSequentialElement(Ty);
        }
        return UnV_.s·getStructElement((cast(结构类型_)(Ty)), Idx);
    }
}
class TY_ {
    this() { }
    static bool s·isSized(类型_ Ty) {
        // If it's a primitive, it is always sized.
        if (Ty.种类 == TypeID_.IntegerTyID || .isFloatingPointTy(Ty) || Ty.种类 == TypeID_.PointerTyID || Ty.种类 == TypeID_.X86_MMXTyID || Ty.种类 == TypeID_.X86_AMXTyID) {
            return true;
        }
        // If it is not something that can have a size (e.g. a function or label),
        // it doesn't have a size.
        if (Ty.种类 != TypeID_.StructTyID && Ty.种类 != TypeID_.ArrayTyID && !.isVectorType(Ty)) {
            return false;
        }
        // Otherwise we have to try harder to decide.
        return TY_.s·isSizedDerivedType(Ty);
    }
    static bool s·isPacked(结构类型_ STy) {
        return STy.是压缩的;
    }
    static bool s·isSizedDerivedType(类型_ Ty) {
        数组类型_ ATy = (cast(数组类型_)(Ty));
        if (ATy !is ··null!(数组类型_)) {
            return TY_.s·isSized(ATy.元素类型);
        }
        向量类型_ VTy = (cast(向量类型_)(Ty));
        if (VTy !is ··null!(向量类型_)) {
            return TY_.s·isSized(VTy.元素类型);
        }
        return ST_.s·isSized((cast(结构类型_)(Ty)));
    }
    static 指针类型_ s·getPointerTo(类型_ Ty, uint 地址) {
        return TGet_.s·PtrTy_get(Ty, 地址);
    }
    static bool s·isEmptyTy(类型_ Ty) {
        数组类型_ ATy = .dyn_cast!(数组类型_)(Ty);
        if (ATy !is ··null!(数组类型_)) {
            ulong NumElements = ATy.数量;
            return NumElements == 0 || TY_.s·isEmptyTy(ATy.元素类型);
        }
        结构类型_ STy = .dyn_cast!(结构类型_)(Ty);
        if (STy !is ··null!(结构类型_)) {
            uint NumElements = ST_.s·getNumElements(STy);
            {
                for (int i = 0; i < NumElements; ++i) {
                    if (!TY_.s·isEmptyTy(ST_.s·getElementType(STy, i))) {
                        return false;
                    }
                }
            }
            return true;
        }
        return false;
    }
}
class ST_ {
    this() { }
    static bool s·isOpaque(结构类型_ ST) {
        return ST.是不透明的;
    }
    static bool s·isPacked(结构类型_ ST) {
        return ST.是压缩的;
    }
    static bool s·isSized(结构类型_ ST) {
        if ((ST.标志 & 类型标志_.SCDB_IsSized) != 0) {
            return true;
        }
        if (ST.是不透明的) {
            return false;
        }
        // Okay, our struct is sized 如果 all of the elements are, but 如果 one of the
        // elements is opaque, the struct isn't sized *yet*, but may become sized in
        // the future, so just bail out without caching.
        foreach (类型_ Ty; ST.ContainedTys) {
            // If the struct contains a scalable vector type, don't consider it sized.
            // This prevents it from being used in loads/stores/allocas/GEPs.
            if (Ty.种类 == TypeID_.ScalableVectorTyID) {
                return false;
            }
            if (!TY_.s·isSized(Ty)) {
                return false;
            }
        }
        ST.标志 |= (cast(整数_)(类型标志_.SCDB_IsSized));
        return true;
    }
    static 类型_ s·getTypeAtIndex(结构类型_ ST, Value V) {
        ulong Idx = .getUniqueInteger((cast(Constant)(V))).getZExtValue();
        return ST_.s·getElementType(ST, (cast(uint)(Idx)));
    }
    static 类型_ s·getElementType(结构类型_ ST, uint Idx) {
        return ST.ContainedTys[Idx];
    }
    static uint s·getNumElements(结构类型_ ST) {
        return (cast(uint)(ST.ContainedTys.length));
    }
    static bool s·indexValid(结构类型_ ST, Value V) {
        if (!.isIntOrIntVectorTy(V.类型, 32)) {
            return false;
        }
        if (V.类型.种类 == TypeID_.ScalableVectorTyID) {
            return false;
        }
        Constant C = (cast(Constant)(V));
        if ((C !is ··null!(Constant)) && .isVectorType(C.类型)) {
            C = .getSplatValue(C, false);
        }
        ConstantInt CU = (cast(ConstantInt)(C));
        return (CU !is ··null!(ConstantInt)) && CU.Val.getZExtValue() < ST_.s·getNumElements(ST);
    }
}
class EEI_ {
    this() { }
    static bool s·isValidOperands(Value Val, Value Index) {
        // V1 and V2 must be vectors of the same type.
        if (!.isVectorType(Val.类型) || !.isIntegerTy(Index.类型)) {
            return false;
        }
        return true;
    }
}
class IEI_ {
    this() { }
    static bool s·isValidOperands(Value Vec, Value Elt, Value Index) {
        // V1 and V2 must be vectors of the same type.
        if (!.isVectorType(Vec.类型)) {
            return false;
        }
        if (Elt.类型 != .cast_!(向量类型_)(Vec.类型).元素类型) {
            return false;
        }
        if (!.isIntegerTy(Index.类型)) {
            return false;
        }
        return true;
    }
}
class SVI_ {
    this() { }
    static bool s·isValidOperands(Value V1, Value V2, int[] Mask) {
        // V1 and V2 must be vectors of the same type.
        if (!.isVectorType(V1.类型) || V1.类型 != V2.类型) {
            return false;
        }
        // Make sure the mask elements make sense.
        uint V1Size = VTy_.s·getElementCount(.cast_!(向量类型_)(V1.类型)).getKnownMinValue();
        foreach (int Elem; Mask) {
            if (Elem != -1 && Elem >= V1Size * 2) {
                return false;
            }
        }
        if (.isScalableVectorType(V1.类型)) {
            if ((Mask[0] != 0 && Mask[0] != -1) || !.is_splat!(int)(Mask)) {
                return false;
            }
        }
        return true;
    }
    static bool s·isValidOperands(Value V1, Value V2, Value Mask) {
        // V1 and V2 must be vectors of the same type.
        if (!.isVectorType(V1.类型) || V1.类型 != V2.类型) {
            return false;
        }
        // Make sure the mask elements make sense.
        向量类型_ MaskTy = .dyn_cast!(向量类型_)(Mask.类型);
        if ((MaskTy is ··null!(向量类型_)) || !.isIntegerTy(MaskTy.元素类型, 32) || .isScalableVectorType(MaskTy) != .isScalableVectorType(V1.类型)) {
            return false;
        }
        if (.isUndefValue(Mask) || .isConstantAggregateZero(Mask)) {
            return true;
        }
        ConstantVector MV = .dyn_cast!(ConstantVector)(Mask);
        if (MV !is ··null!(ConstantVector)) {
            uint V1Size = .cast_!(向量类型_)(V1.类型).数量;
            foreach (Value Op; MV.Ops) {
                ConstantInt CI = .dyn_cast!(ConstantInt)(Op);
                if (CI !is ··null!(ConstantInt)) {
                    if (CI.Val.uge(V1Size * 2)) {
                        return false;
                    }
                    else if (!.isUndefValue(Op)) {
                        return false;
                    }
                }
            }
            return true;
        }
        ConstantDataSequential CDS = .dyn_cast!(ConstantDataSequential)(Mask);
        if (CDS !is ··null!(ConstantDataSequential)) {
            uint V1Size = .cast_!(向量类型_)(V1.类型).数量;
            uint L = .cast_!(向量类型_)(MaskTy).数量;
            {
                for (uint i = 0; i < L; ++i) {
                    if (CDS_.s·getElementAsInteger(CDS, i) >= V1Size * 2) {
                        return false;
                    }
                }
            }
            return true;
        }
        return false;
    }
    static int[] s·getShuffleMask(Constant Mask) {
        ElementCount EC = VTy_.s·getElementCount(.cast_!(向量类型_)(Mask.类型));
        if (.isConstantAggregateZero(Mask)) {
            uint 数量 = EC.getKnownMinValue();
            return .crateSmallVector!(int)(数量, (cast(int)(0)));
        }
        int[] Res = 创建数组!(int)();
        Res.length = EC.getKnownMinValue();
        if (EC.isScalable()) {
            int MaskVal = .isUndefValue(Mask) ? -1 : 0;
            {
                for (int i = 0; i < EC.getKnownMinValue(); ++i) {
                    Res[i] = MaskVal;
                }
            }
            return Res;
        }
        ConstantDataSequential CDS = .dyn_cast!(ConstantDataSequential)(Mask);
        if (CDS !is ··null!(ConstantDataSequential)) {
            {
                for (uint i = 0; i < Res.length; ++i) {
                    Res[i] = (cast(int)(CDS_.s·getElementAsInteger(CDS, i)));
                }
            }
            return Res;
        }
        {
            for (int i = 0; i < Res.length; ++i) {
                Constant C = .getAggregateElement(Mask, i);
                Res[i] = .isUndefValue(C) ? -1 : (cast(int)(.cast_!(ConstantInt)(C).Val.getZExtValue()));
            }
        }
        return Res;
    }
    static Constant s·convertShuffleMaskForBitcode(int[] Mask, 类型_ ResultTy) {
        整数类型_ Int32Ty_ = TGet_.s·IntTy_get(32);
        if (.isScalableVectorType(ResultTy)) {
            向量类型_ VecTy = TGet_.s·VTy_get(Int32Ty_, true, (cast(uint)(Mask.length)));
            if (Mask[0] == 0) {
                return CGet_.s·getNullValue(VecTy);
            }
            return CGet_.s·UndefValue_get(VecTy);
        }
        Constant[] MaskConst = 创建数组!(Constant)();
        foreach (int Elem; Mask) {
            if (Elem == -1) {
                .追加!(Constant)(MaskConst, CGet_.s·UndefValue_get(Int32Ty_));
            }
            else {
                .追加!(Constant)(MaskConst, CGet_.s·CInt_get(Int32Ty_, Elem, false));
            }
        }
        return CGet_.s·Vector_get(MaskConst);
    }
}
class GEV_ {
    this() { }
    static 类型_ s·getIndexedType(类型_ Agg, uint[] Idxs) {
        foreach (uint Index; Idxs) {
            数组类型_ AT = .dyn_cast!(数组类型_)(Agg);
            if (AT !is ··null!(数组类型_)) {
                if (Index >= AT.数量) {
                    return ··null!(类型_);
                }
                Agg = AT.元素类型;
            }
            else if (.dyn_cast!(结构类型_)(Agg) !is ··null!(结构类型_)) {
                结构类型_ ST = .dyn_cast!(结构类型_)(Agg);
                if (Index >= ST_.s·getNumElements(ST)) {
                    return ··null!(类型_);
                }
                Agg = ST_.s·getElementType(ST, Index);
            }
            else {
                return ··null!(类型_);
            }
        }
        return Agg;
    }
}
class GEP_ {
    this() { }
    static GetElementPtrConstantExpr s·create(类型_ SrcElementTy, Constant C, Constant[] IdxList, 类型_ DestTy, ulong Flags) {
        GetElementPtrConstantExpr ex = new GetElementPtrConstantExpr();
        ex.类型 = DestTy;
        ex.Opc = InstructionKind_.GetElementPtr;
        ex.SrcElementTy = SrcElementTy;
        .追加!(Value)(ex.Ops, C);
        .追加!(Value)(ex.Ops, cast(Value[])(IdxList));
        ex.ResElementTy = GEP_.s·getIndexedType(SrcElementTy, (cast(Value[])(IdxList)));
        ex.SubclassOptionalData = Flags;
        return ex;
    }
    static uint s·getInRangeIndex(GetElementPtrConstantExpr GEP) {
        if ((GEP.SubclassOptionalData >> 1) == 0) {
            return 0;
        }
        return (cast(uint)((GEP.SubclassOptionalData >> 1) - 1));
    }
    static 类型_ s·getIndexedType(类型_ Ty, Value[] IdxList) {
        if ((IdxList is ··null!(Value[])) || IdxList.length == 0) {
            return Ty;
        }
        foreach (Value V; IdxList) {
            Ty = GEP_.s·getTypeAtIndex(Ty, V);
            if (Ty is ··null!(类型_)) {
                return Ty;
            }
        }
        return Ty;
    }
    static 类型_ s·getIndexedType(类型_ Ty, uint[] IdxList) {
        if ((IdxList is ··null!(uint[])) || IdxList.length == 0) {
            return Ty;
        }
        foreach (uint V; IdxList) {
            Ty = GEP_.s·getTypeAtIndex(Ty, V);
            if (Ty is ··null!(类型_)) {
                return Ty;
            }
        }
        return Ty;
    }
    static 类型_ s·getGEPReturnType(类型_ ElTy, Value Ptr, Value[] IdxList) {
        指针类型_ OrigPtrTy = .cast_!(指针类型_)(.getScalarType(Ptr.类型));
        uint AddrSpace = OrigPtrTy.地址;
        类型_ ResultElemTy = GEP_.s·getIndexedType(ElTy, IdxList);
        类型_ PtrTy = PTy_.s·isOpaque(OrigPtrTy) ? TGet_.s·PtrTy_get(返回零值!(类型_)(), AddrSpace) : TGet_.s·PtrTy_get(ResultElemTy, AddrSpace);
        // Vector GEP
        向量类型_ PtrVTy = .cast_!(向量类型_)(Ptr.类型);
        if (PtrVTy !is ··null!(向量类型_)) {
            ElementCount EltCount = VTy_.s·getElementCount(PtrVTy);
            return TGet_.s·VTy_get(PtrTy, false, EltCount.getValue());
        }
        foreach (Value Index; IdxList) {
            向量类型_ IndexVTy = .cast_!(向量类型_)(Index.类型);
            if (IndexVTy !is ··null!(向量类型_)) {
                ElementCount EltCount = VTy_.s·getElementCount(IndexVTy);
                return TGet_.s·VTy_get(PtrTy, false, EltCount.getValue());
            }
        }
        // Scalar GEP
        return PtrTy;
    }
    static 类型_ s·getTypeAtIndex(类型_ Ty, Value Idx) {
        结构类型_ Struct = (cast(结构类型_)(Ty));
        if (Struct !is ··null!(结构类型_)) {
            if (!ST_.s·indexValid(Struct, Idx)) {
                return ··null!(类型_);
            }
            return ST_.s·getTypeAtIndex(Struct, Idx);
        }
        if (!.isIntOrIntVectorTy(Idx.类型)) {
            return ··null!(类型_);
        }
        数组类型_ Array = (cast(数组类型_)(Ty));
        if (Array !is ··null!(数组类型_)) {
            return Array.元素类型;
        }
        向量类型_ Vector = (cast(向量类型_)(Ty));
        if (Vector !is ··null!(向量类型_)) {
            return Vector.元素类型;
        }
        return ··null!(类型_);
    }
    static 类型_ s·getTypeAtIndex(类型_ Ty, uint Idx) {
        结构类型_ Struct = .cast_!(结构类型_)(Ty);
        if (Struct !is ··null!(结构类型_)) {
            if (Idx >= Struct.ContainedTys.length) {
                return ··null!(类型_);
            }
            return ST_.s·getElementType(Struct, Idx);
        }
        数组类型_ Array = .cast_!(数组类型_)(Ty);
        if (Array !is ··null!(数组类型_)) {
            return Array.元素类型;
        }
        向量类型_ Vector = .cast_!(向量类型_)(Ty);
        if (Vector !is ··null!(向量类型_)) {
            return Vector.元素类型;
        }
        return ··null!(类型_);
    }
    static bool s·hasAllZeroIndices(GetElementPtrConstantExpr gep) {
        {
            for (int i = 1; i < gep.Ops.length; ++i) {
                Value I = gep.Ops[i];
                ConstantInt C = .dyn_cast!(ConstantInt)(I);
                if (C !is ··null!(ConstantInt)) { }
                return false;
            }
        }
        return true;
    }
}
class CFold_ {
    this() { }
    static Constant s·BitCastConstantVector(Constant CV, 向量类型_ DstTy) {
        if (.isAllOnesValue(CV)) {
            return .getAllOnesValue(DstTy);
        }
        if (.isNullValue(CV)) {
            return CGet_.s·getNullValue(DstTy);
        }
        // Do not iterate on scalable vector. The num of elements is unknown at
        // compile-time.
        if (DstTy.种类 == TypeID_.ScalableVectorTyID) {
            return 返回零值!(Constant)();
        }
        // If this cast_ changes element count then we can't handle it here:
        // doing so requires endianness information.  This should be handled by
        // Analysis/ConstantFolding.cpp
        uint NumElts = DstTy.数量;
        向量类型_ ···temp·0·_1 = (cast(向量类型_)(CV.类型));
        if ((···temp·0·_1 is ··null!(向量类型_)) || (cast(向量类型_)(CV.类型)).可扩展的 || NumElts != (cast(向量类型_)(CV.类型)).数量 || DstTy.可扩展的) {
            return 返回零值!(Constant)();
        }
        类型_ DstEltTy = DstTy.元素类型;
        // Fast path 循环 splatted constants.
        Constant Splat = .getSplatValue(CV, false);
        if (Splat !is ··null!(Constant)) {
            return CGet_.s·Vector_getSplat(VTy_.s·getElementCount(DstTy), CEGet_.s·getBitCast(Splat, DstEltTy));
        }
        Constant[] Result = 创建数组!(Constant)();
        整数类型_ Ty = TGet_.s·IntTy_get(32);
        {
            for (uint i = 0; i != NumElts; ++i) {
                Constant C = CEGet_.s·getExtractElement(CV, CGet_.s·CInt_get(new APInt_(32, i)));
                C = CEGet_.s·getBitCast(C, DstEltTy);
                .追加!(Constant)(Result, C);
            }
        }
        return CGet_.s·Vector_get(Result);
    }
    static uint s·foldConstantCastPair(uint opc, ConstantExpr Op, 类型_ DstTy) {
        // The types and opcodes 循环 the two Cast constant expressions
        类型_ SrcTy = Op.Ops[0].类型;
        类型_ MidTy = Op.类型;
        InstructionKind_ firstOp = Op.Opc;
        InstructionKind_ secondOp = .转换枚举!(InstructionKind_)(opc);
        // Assume that pointers are never more than 64 bits wide, and only use this
        // 循环 the middle type. Otherwise we could end up folding away illegal
        // bitcasts between address spaces with different sizes.
        整数类型_ FakeIntPtrTy = .Int64Ty;
        return (cast(uint)(.CastInst_isEliminableCastPair(firstOp, secondOp, SrcTy, MidTy, DstTy, 返回零值!(类型_)(), FakeIntPtrTy, 返回零值!(类型_)())));
    }
    static Constant s·FoldBitCast(Constant V, 类型_ DestTy) {
        类型_ SrcTy = V.类型;
        if (SrcTy == DestTy) {
            return // no-op cast_
             V;
        } // no-op cast_
        // Check to see 如果 we are casting a pointer to an aggregate to a pointer to
        // the first element.  If so, 返回 the appropriate GEP instruction.
        指针类型_ PTy = (cast(指针类型_)(V.类型));
        if (PTy !is ··null!(指针类型_)) {
            指针类型_ DPTy = (cast(指针类型_)(DestTy));
            if (DPTy !is ··null!(指针类型_)) {
                if (PTy.地址 == DPTy.地址 && TY_.s·isSized(PTy.类型)) {
                    Value[] IdxList = 创建数组!(Value)();
                    Constant Zero = CGet_.s·getNullValue(.Int32Ty);
                    .追加!(Value)(IdxList, Zero);
                    类型_ ElTy = PTy.类型;
                    while((ElTy !is ··null!(类型_)) && ElTy != DPTy.类型) {
                        ElTy = GEP_.s·getTypeAtIndex(ElTy, CGet_.s·CInt_get(APInt_getZero(64)));
                        .追加!(Value)(IdxList, Zero);
                    }
                    if (ElTy == DPTy.类型) {
                        // This GEP is inbounds because all indices are zero.
                        return (cast(Constant)(CEGet_.s·getInBoundsGetElementPtr(PTy.类型, V, IdxList)));
                    }
                }
            }
        }
        // Handle casts from one vector constant to another.  We know that the src
        // and dest type have the same size (otherwise its an illegal cast_).
        向量类型_ DestPTy = (cast(向量类型_)(DestTy));
        if (DestPTy !is ··null!(向量类型_)) {
            SrcTy = (cast(向量类型_)(V.类型));
            if (SrcTy !is ··null!(类型_)) {
                SrcTy = 返回零值!(向量类型_)();
                // First, check 循环 null.  Undef is already handled.
                if (V.种类 == ValueTy_.ConstantAggregateZeroVal) {
                    return CGet_.s·getNullValue(DestTy);
                }
                // Handle ConstantVector and ConstantAggregateVector.
                return CFold_.s·BitCastConstantVector(V, DestPTy);
            }
            // Canonicalize scalar-to-vector bitcasts into vector-to-vector bitcasts
            // This allows 循环 other simplifications (although some of them
            // can only be handled by Analysis/ConstantFolding.cpp).
            if (V.种类 == ValueTy_.ConstantIntVal || V.种类 == ValueTy_.ConstantFPVal) {
                return CEGet_.s·getBitCast(CGet_.s·Vector_get([V]), DestPTy);
            }
        }
        // Finally, implement bitcast folding now.   The code below doesn't handle
        // bitcast right.
        if (V.种类 == ValueTy_.ConstantPointerNullVal) // ptr.ptr cast_.
         {
            return CGet_.s·PointerNull_get((cast(指针类型_)(DestTy)));
        }
        // Handle integral constant input.
        ConstantInt CI = (cast(ConstantInt)(V));
        if (CI !is ··null!(ConstantInt)) {
            if (DestTy.种类 == TypeID_.IntegerTyID) {
                // Integral . Integral. This is a no-op because the bit widths must
                // be the same. Consequently, we just fold to V.
                return V;
            }
            // See note below regarding the PPC_FP128 restriction.
            if (.isFloatingPointTy(DestTy) && DestTy.种类 != TypeID_.PPC_FP128TyID) {
                return CGet_.s·CFP_get(new APFloat_(.getFltSemantics(DestTy), CI.Val));
            }
            // Otherwise, can't fold this (vector?)
            return 返回零值!(Constant)();
        }
        // Handle ConstantFP input: FP . Integral.
        ConstantFP FP = (cast(ConstantFP)(V));
        if (FP !is ··null!(ConstantFP)) {
            // PPC_FP128 is really the sum of two consecutive doubles, where the first
            // double is always stored first in memory, regardless of the target
            // endianness. The memory layout of i128, however, depends on the target
            // endianness, and so we can't fold this without target endianness
            // information. This should instead be handled by
            // Analysis/ConstantFolding.cpp
            if (FP.类型.种类 == TypeID_.PPC_FP128TyID) {
                return 返回零值!(Constant)();
            }
            // Make sure dest type is compatible with the folded integer constant.
            if (DestTy.种类 != TypeID_.IntegerTyID) {
                return 返回零值!(Constant)();
            }
            return CGet_.s·CInt_get(FP.Val.bitcastToAPInt());
        }
        return 返回零值!(Constant)();
    }
    static Constant s·ExtractConstantBytes(Constant C, uint ByteStart, uint ByteSize) {
        uint CSize = (cast(整数类型_)(C.类型)).位数 / 8;
        // Constant Integers are simple.
        ConstantInt CI = (cast(ConstantInt)(C));
        if (CI !is ··null!(ConstantInt)) {
            APInt_ V = CI.Val;
            if (ByteStart != 0) {
                V.lshrInPlace(ByteStart * 8);
            }
            V = V.trunc(ByteSize * 8);
            return CGet_.s·CInt_get(V);
        }
        // In the input is a constant expr, we might be able to recursively simplify.
        // If not, we definitely can't do anything.
        ConstantExpr CE = (cast(ConstantExpr)(C));
        if (CE is ··null!(ConstantExpr)) {
            return 返回零值!(Constant)();
        }
        switch (CE.Opc) {
            case InstructionKind_.Or: {
                Constant RHS = CFold_.s·ExtractConstantBytes((cast(Constant)(CE.Ops[1])), ByteStart, ByteSize);
                if (RHS is ··null!(Constant)) {
                    return 返回零值!(Constant)();
                }
                // X | -1 . -1.
                ConstantInt RHSC = (cast(ConstantInt)(RHS));
                if (RHSC !is ··null!(ConstantInt)) { }
                Constant LHS = CFold_.s·ExtractConstantBytes((cast(Constant)(CE.Ops[0])), ByteStart, ByteSize);
                if (LHS is ··null!(Constant)) {
                    return 返回零值!(Constant)();
                }
                return CEGet_.s·getOr(LHS, RHS);
            }
            case InstructionKind_.And: {
                Constant RHS = CFold_.s·ExtractConstantBytes((cast(Constant)(CE.Ops[1])), ByteStart, ByteSize);
                if (RHS is ··null!(Constant)) {
                    return 返回零值!(Constant)();
                }
                // X & 0 . 0.
                if (.isNullValue(RHS)) {
                    return RHS;
                }
                Constant LHS = CFold_.s·ExtractConstantBytes((cast(Constant)((CE.Ops[0]))), ByteStart, ByteSize);
                if (LHS is ··null!(Constant)) {
                    return 返回零值!(Constant)();
                }
                return CEGet_.s·getAnd(LHS, RHS);
            }
            case InstructionKind_.LShr: {
                ConstantInt Amt = (cast(ConstantInt)(CE.Ops[1]));
                if (Amt is ··null!(ConstantInt)) {
                    return 返回零值!(Constant)();
                }
                APInt_ ShAmt = Amt.Val;
                // Cannot analyze non-byte shifts.
                if (!(ShAmt.Op且等(7)).Op等等(0)) {
                    return 返回零值!(Constant)();
                }
                ShAmt.lshrInPlace(3);
                // If the extract is known to be all zeros, 返回 zero.
                if (ShAmt.uge(CSize - ByteStart)) {
                    return CGet_.s·getNullValue(TGet_.s·IntTy_get(ByteSize * 8));
                }
                // If the extract is known to be fully in the input, extract it.
                if (ShAmt.ule(CSize - (ByteStart + ByteSize))) {
                    return CFold_.s·ExtractConstantBytes((cast(Constant)((CE.Ops[0]))), (cast(uint)(ByteStart + ShAmt.getZExtValue())), ByteSize);
                }
                // TODO: Handle the 'partially zero' 若是.
                return 返回零值!(Constant)();
            }
            case InstructionKind_.Shl: {
                ConstantInt Amt = (cast(ConstantInt)(CE.Ops[1]));
                if (Amt is ··null!(ConstantInt)) {
                    return 返回零值!(Constant)();
                }
                APInt_ ShAmt = Amt.Val;
                // Cannot analyze non-byte shifts.
                if (!(ShAmt.Op且等(7)).Op等等(0)) {
                    return 返回零值!(Constant)();
                }
                ShAmt.lshrInPlace(3);
                // If the extract is known to be all zeros, 返回 zero.
                if (ShAmt.uge(ByteStart + ByteSize)) {
                    return CGet_.s·getNullValue(TGet_.s·IntTy_get(ByteSize * 8));
                }
                // If the extract is known to be fully in the input, extract it.
                if (ShAmt.ule(ByteStart)) {
                    return CFold_.s·ExtractConstantBytes((cast(Constant)(CE.Ops[0])), (cast(uint)(ByteStart - ShAmt.getZExtValue())), ByteSize);
                }
                // TODO: Handle the 'partially zero' 若是.
                return 返回零值!(Constant)();
            }
            case InstructionKind_.ZExt: {
                uint SrcBitSize = (cast(整数类型_)(CE.Ops[0].类型)).位数;
                if (ByteStart * 8 >= SrcBitSize) {
                    return CGet_.s·getNullValue(TGet_.s·IntTy_get(ByteSize * 8));
                }
                // If exactly extracting the input, 返回 it.
                if (ByteStart == 0 && ByteSize * 8 == SrcBitSize) {
                    return (cast(Constant)(CE.Ops[0]));
                }
                // If extracting something completely in the input, 如果 the input is a
                // multiple of 8 bits, recurse.
                if ((SrcBitSize & 7) == 0 && (ByteStart + ByteSize) * 8 <= SrcBitSize) {
                    return CFold_.s·ExtractConstantBytes((cast(Constant)(CE.Ops[0])), ByteStart, ByteSize);
                }
                // Otherwise, 如果 extracting a subset of the input, which is not multiple of
                // 8 bits, do a shift and trunc to get the bits.
                if ((ByteStart + ByteSize) * 8 < SrcBitSize) {
                    Constant Res = (cast(Constant)(CE.Ops[0]));
                    if (ByteStart != 0) {
                        Res = CEGet_.s·getLShr(Res, CGet_.s·CInt_get(Res.类型, (cast(ulong)(ByteStart * 8)), false), false);
                    }
                    return CEGet_.s·getTrunc(Res, TGet_.s·IntTy_get(ByteSize * 8));
                }
                // TODO: Handle the 'partially zero' 若是.
                return 返回零值!(Constant)();
            }
            default: {
                return 返回零值!(Constant)();
            }
        }
    }
    static Constant s·ConstantFoldCastInstruction(uint opc, Constant V, 类型_ DestTy) {
        if (.isPoisonValue(V)) {
            return CGet_.s·PoisonValue_get(DestTy);
        }
        if (.isUndefValue(V)) {
            // zext(undef) = 0, because the top bits will be zero.
            // sext(undef) = 0, because the top bits will all be the same.
            // [us]itofp(undef) = 0, because the result value is bounded.
            if (opc == InstructionKind_.ZExt || opc == InstructionKind_.SExt || opc == InstructionKind_.UIToFP || opc == InstructionKind_.SIToFP) {
                return CGet_.s·getNullValue(DestTy);
            }
            return CGet_.s·UndefValue_get(DestTy);
        }
        if (.isNullValue(V) && DestTy.种类 != TypeID_.X86_MMXTyID && DestTy.种类 != TypeID_.X86_AMXTyID && opc != InstructionKind_.AddrSpaceCast) {
            return CGet_.s·getNullValue(DestTy);
        }
        // If the cast_ operand is a constant expression, there's a few things we can
        // do to try to simplify it.
        ConstantExpr CE = (cast(ConstantExpr)(V));
        if (CE !is ··null!(ConstantExpr)) {
            if (CExp_.s·isCast(CE)) {
                // Try hard to fold cast_ of cast_ because they are often eliminable.
                uint newOpc = CFold_.s·foldConstantCastPair(opc, CE, DestTy);
                if (newOpc != 0) {
                    return CEGet_.s·getCast(newOpc, (cast(Constant)(CE.Ops[0])), DestTy);
                }
            }
            else if (CE.Opc == InstructionKind_.GetElementPtr && opc != InstructionKind_.AddrSpaceCast && GEP_.s·getInRangeIndex((cast(GetElementPtrConstantExpr)(CE))) == 0 && !.isVectorType(CE.类型)) {
                bool isAllNull = true;
                {
                    for (int i = 1; i != CE.Ops.length; ++i) {
                        if (!.isNullValue((cast(Constant)(CE.Ops[i])))) {
                            isAllNull = false;
                            break;
                        }
                    }
                }
                if (isAllNull) {
                    // This is casting one pointer type to another, always BitCast
                    return CEGet_.s·getPointerCast((cast(Constant)(CE.Ops[0])), DestTy);
                }
            }
        }
        // If the cast_ operand is a constant vector, perform the cast_ by
        // operating on each element. In the cast_ of bitcasts, the element
        // count may be mismatched; don't attempt to handle that here.
        if ((.isConstantVector(V) || .isConstantDataVector(V)) && .isVectorType(DestTy) && .cast_!(向量类型_)(DestTy).数量 == .cast_!(向量类型_)(V.类型).数量) {
            向量类型_ DestVecTy = (cast(向量类型_)(DestTy));
            类型_ DstEltTy = DestVecTy.元素类型;
            // Fast path 循环 splatted constants.
            Constant Splat = .getSplatValue(V, false);
            if (Splat !is ··null!(Constant)) {
                return CGet_.s·Vector_getSplat(VTy_.s·getElementCount((cast(向量类型_)(DestTy))), CEGet_.s·getCast(opc, Splat, DstEltTy));
            }
            Constant[] res = 创建数组!(Constant)();
            类型_ Ty = TGet_.s·IntTy_get(32);
            {
                uint i = 0;
                uint e = (cast(向量类型_)(V.类型)).数量;
                for (; i != e; ++i) {
                    Constant C = CEGet_.s·getExtractElement(V, CGet_.s·CInt_get(Ty, i, false));
                    .追加!(Constant)(cast(Constant[])(res), CEGet_.s·getCast(opc, C, DstEltTy));
                }
            }
            return CGet_.s·Vector_get(res);
        }
        // We actually have to do a cast_ now. Perform the cast_ according to the
        // opcode specified.
        switch (opc) {
            case InstructionKind_.FPTrunc:
            case InstructionKind_.FPExt: {
                ConstantFP FPC = (cast(ConstantFP)(V));
                if (FPC !is ··null!(ConstantFP)) {
                    bool ignored = false;
                    APFloat_ Val = FPC.Val;
                    Val.convert(.isHalfTy(DestTy) ? IEEEhalf() : .isFloatTy(DestTy) ? IEEEsingle() : .isDoubleTy(DestTy) ? IEEEdouble() : .isX86_FP80Ty(DestTy) ? x87DoubleExtended() : .isFP128Ty(DestTy) ? IEEEquad() : .isPPC_FP128Ty(DestTy) ? PPCDoubleDouble() : Bogus(), rmNearestTiesToEven, ignored);
                    return CGet_.s·CFP_get(Val);
                }
                return 返回零值!(Constant)();
            } // Can't fold.
            case InstructionKind_.FPToUI:
            case InstructionKind_.FPToSI: {
                ConstantFP FPC = (cast(ConstantFP)(V));
                if (FPC !is ··null!(ConstantFP)) {
                    APFloat_ VF = FPC.Val;
                    bool ignored = false;
                    uint DestBitWidth = .cast_!(整数类型_)(DestTy).位数;
                    APSInt_ IntVal = new APSInt_(DestBitWidth, opc == InstructionKind_.FPToUI);
                    if (APFloat_OpStatus_.opInvalidOp == VF.convertToInteger(IntVal, rmTowardZero, ignored)) {
                        // Undefined behavior invoked - the destination type can't represent
                        // the input constant.
                        return CGet_.s·PoisonValue_get(DestTy);
                    }
                    return CGet_.s·CInt_get(IntVal);
                }
                return 返回零值!(Constant)();
            } // Can't fold.
            case InstructionKind_.IntToPtr: {
                if (.isNullValue(V)) // Is it an integral null value?
                 {
                    return CGet_.s·PointerNull_get(.cast_!(指针类型_)(DestTy));
                }
                return 返回零值!(Constant)();
            } // Other pointer types cannot be casted
            case InstructionKind_.PtrToInt: {
                // Is it a null pointer value?
                if (.isNullValue(V)) {
                    return CGet_.s·CInt_get(DestTy, 0, false);
                }
                // Other pointer types cannot be casted
                return 返回零值!(Constant)();
            }
            case InstructionKind_.UIToFP:
            case InstructionKind_.SIToFP: {
                ConstantInt CI = .cast_!(ConstantInt)(V);
                if (CI !is ··null!(ConstantInt)) {
                    APInt_ api = CI.Val;
                    APFloat_ apf = new APFloat_(.getFltSemantics(DestTy), APInt_getZero((cast(uint)(.getPrimitiveSizeInBits(DestTy).getValue()))));
                    apf.convertFromAPInt(api, opc == InstructionKind_.SIToFP, rmNearestTiesToEven);
                    return CGet_.s·CFP_get(apf);
                }
                return 返回零值!(Constant)();
            }
            case InstructionKind_.ZExt: {
                ConstantInt CI = .cast_!(ConstantInt)(V);
                if (CI !is ··null!(ConstantInt)) {
                    uint BitWidth = .cast_!(整数类型_)(DestTy).位数;
                    return CGet_.s·CInt_get(CI.Val.zext(BitWidth));
                }
                return 返回零值!(Constant)();
            }
            case InstructionKind_.SExt: {
                ConstantInt CI = .cast_!(ConstantInt)(V);
                if (CI !is ··null!(ConstantInt)) {
                    uint BitWidth = .cast_!(整数类型_)(DestTy).位数;
                    return CGet_.s·CInt_get(CI.Val.sext(BitWidth));
                }
                return 返回零值!(Constant)();
            }
            case InstructionKind_.Trunc: {
                if (.isVectorType(V.类型)) {
                    return 返回零值!(Constant)();
                }
                uint DestBitWidth = .cast_!(整数类型_)(DestTy).位数;
                ConstantInt CI = .cast_!(ConstantInt)(V);
                if (CI !is ··null!(ConstantInt)) {
                    return CGet_.s·CInt_get(CI.Val.trunc(DestBitWidth));
                }
                // The input must be a constantexpr.  See 如果 we can simplify this based on
                // the bytes we are demanding.  Only do this 如果 the source and dest are an
                // even multiple of a byte.
                if ((DestBitWidth & 7) == 0 && (.cast_!(整数类型_)(V.类型).位数 & 7) == 0) {
                    Constant Res = CFold_.s·ExtractConstantBytes(V, 0, DestBitWidth / 8);
                    if (Res !is ··null!(Constant)) {
                        return Res;
                    }
                }
                return 返回零值!(Constant)();
            }
            case InstructionKind_.BitCast: {
                return CFold_.s·FoldBitCast(V, DestTy);
            }
            case InstructionKind_.AddrSpaceCast: {
                return 返回零值!(Constant)();
            }
            default: {
                assert(false, "Failed to cast_ constant expression"c);
                break;
            }
        }
        return 返回零值!(Constant)();
    }
    static Constant s·foldGEPOfGEP(GetElementPtrConstantExpr GEP, 类型_ PointeeTy, bool InBounds, Value[] Idxs) {
        if (PointeeTy != GEP.ResElementTy) {
            return ··null!(Constant);
        }
        Constant Idx0 = .cast_!(Constant)(Idxs[0]);
        if (.isNullValue(Idx0)) {
            // Handle the simple case of a zero index.
            Value[] NewIndices = 创建数组!(Value)();
            Value[] os = (cast(Value[])(GEP.Ops[1 .. $]));
            Value[] ids = Idxs[1 .. $];
            .追加!(Value)(NewIndices, os);
            .追加!(Value)(NewIndices, ids);
            return CEGet_.s·getGetElementPtr(GEP.SrcElementTy, .cast_!(Constant)(GEP.Ops[0]), NewIndices, InBounds && (GEP.SubclassOptionalData & 1) != 0, (((GEP.SubclassOptionalData >> 1) == 0) ? (cast(uint)(0)) : (cast(uint)((GEP.SubclassOptionalData >> 1) - 1))));
        }
        类型_ LastI = GEP.SrcElementTy;
        long NumElements = -1;
        {
            for (int i = 1; i < GEP.Ops.length; ++i) {
                Value OpIt = GEP.Ops[i];
                if (LastI.种类 == TypeID_.ArrayTyID) {
                    NumElements = (cast(数组类型_)(LastI)).数量;
                }
                else if (LastI.种类 == TypeID_.FixedVectorTyID) {
                    NumElements = (cast(向量类型_)(LastI)).数量;
                }
                else if (LastI.种类 == TypeID_.ScalableVectorTyID) {
                    NumElements = -1;
                }
                LastI = GEP_.s·getTypeAtIndex(LastI, OpIt);
            }
        }
        if (LastI.种类 == TypeID_.StructTyID) {
            return ··null!(Constant);
        }
        ConstantInt CI = .cast_!(ConstantInt)(Idx0);
        if (CI is ··null!(ConstantInt)) {
            return ··null!(Constant);
        }
        if (NumElements != -1 && !.isIndexInRangeOfArrayType(NumElements, CI)) {
            return ··null!(Constant);
        }
        // TODO: This code may be extended to handle vectors as well.
        Constant LastIdx = .cast_!(Constant)(GEP.Ops[GEP.Ops.length - 1]);
        类型_ LastIdxTy = LastIdx.类型;
        if (.isVectorType(LastIdxTy)) {
            return ··null!(Constant);
        }
        Value[] NewIndices = 创建数组!(Value)(); // SmallVector<Value*, 16> ;
        Value[] os = (cast(Value[])(GEP.Ops[1 .. $-1]));
        .追加!(Value)(NewIndices, os);
        // Add the last index of the source with the first index of the new GEP.
        // Make sure to handle the case when they are actually different types.
        if (LastIdxTy != Idx0.类型) {
            long CommonExtendedWidth = 核心.最大((cast(整数类型_)(LastIdxTy)).位数, (cast(整数类型_)(Idx0.类型)).位数);
            CommonExtendedWidth = 核心.最大(CommonExtendedWidth, 64u);
            整数类型_ CommonTy = TGet_.s·IntTy_get((cast(uint)(CommonExtendedWidth)));
            Idx0 = CEGet_.s·getSExtOrBitCast(Idx0, CommonTy);
            LastIdx = CEGet_.s·getSExtOrBitCast(LastIdx, CommonTy);
        }
        .追加!(Value)(NewIndices, CEGet_.s·get(InstructionKind_.Add, Idx0, LastIdx, 0));
        .追加!(Value)(NewIndices, Idxs[1 .. $]);
        // The combined GEP normally inherits its index inrange attribute from
        // the inner GEP, but 如果 the inner GEP's last index was adjusted by the
        // outer GEP, any inbounds attribute on that index is invalidated.
        uint IRIndex = (((GEP.SubclassOptionalData >> 1) == 0) ? (cast(uint)(0)) : (cast(uint)((GEP.SubclassOptionalData >> 1) - 1)));
        if (IRIndex != 0 && IRIndex == GEP.Ops.length - 2) {
            IRIndex = 0;
        }
        return CEGet_.s·getGetElementPtr(GEP.SrcElementTy, .cast_!(Constant)(GEP.Ops[0]), NewIndices, InBounds && (GEP.SubclassOptionalData & 1) != 0, IRIndex);
    }
    static Constant s·ConstantFoldGetElementPtr(类型_ PointeeTy, Constant C, bool InBounds, uint InRangeIndex, Value[] Idxs) {
        void delegate(long) 下个;
        类型_ GEPTy;
        Constant Idx0;
        ConstantExpr CE;
        Constant[] NewIdxs;
        类型_ Ty;
        类型_ Prev;
        bool Unknown;
        void 下个·func(long i) {
            Value OpIt;
            Prev = Ty;
            OpIt = Idxs[i];
            Ty = GEP_.s·getTypeAtIndex(Ty, OpIt);
        }
        下个 = &下个·func;
        if ((Idxs is ··null!(Value[])) || Idxs.length == 0) {
            return C;
        }
        GEPTy = GEP_.s·getGEPReturnType(PointeeTy, C, Idxs);
        if (.isPoisonValue(C)) {
            return CGet_.s·PoisonValue_get(GEPTy);
        }
        if (.isUndefValue(C)) {
            // If inbounds, we can choose an out-of-bounds pointer as a base pointer.
            return InBounds ? CGet_.s·PoisonValue_get(GEPTy) : CGet_.s·UndefValue_get(GEPTy);
        }
        Idx0 = .cast_!(Constant)(Idxs[0]);
        if (Idxs.length == 1 && (.isNullValue(Idx0) || .isUndefValue(Idx0))) {
            return .isVectorType(GEPTy) && !.isVectorType(C.类型) ? CGet_.s·Vector_getSplat(VTy_.s·getElementCount(.cast_!(向量类型_)(GEPTy)), C) : C;
        }
        if (.isNullValue(C)) {
            bool isNull = true;
            {
                for (int i = 0; i < Idxs.length; ++i) {
                    if (!.isUndefValue(.cast_!(Constant)(Idxs[i])) && !.isNullValue(.cast_!(Constant)(Idxs[i]))) {
                        isNull = false;
                        break;
                    }
                }
            }
            if (isNull) {
                指针类型_ PtrTy = .cast_!(指针类型_)(.getScalarType(C.类型));
                类型_ Ty2 = GEP_.s·getIndexedType(PointeeTy, Idxs);
                assert(Ty2 !is ··null!(类型_), "Invalid indices 循环 GEP!"c);
                指针类型_ OrigGEPTy = TGet_.s·PtrTy_get(Ty2, PtrTy.地址);
                GEPTy = TGet_.s·PtrTy_get(Ty2, PtrTy.地址);
                向量类型_ VT = .cast_!(向量类型_)(C.类型);
                if (VT !is ··null!(向量类型_)) {
                    GEPTy = TGet_.s·VTy_get(OrigGEPTy, false, VTy_.s·getElementCount(VT).getValue());
                }
                {
                    // The GEP returns a vector of pointers when one of more of
                    // its arguments is a vector.
                    for (int i = 0; i < Idxs.length; ++i) {
                        VT = .cast_!(向量类型_)(Idxs[i].类型);
                        if (VT !is ··null!(向量类型_)) {
                            GEPTy = TGet_.s·VTy_get(OrigGEPTy, false, VTy_.s·getElementCount(VT).getValue());
                            break;
                        }
                    }
                }
                return CGet_.s·getNullValue(GEPTy);
            }
        }
        CE = .cast_!(ConstantExpr)(C);
        if (CE !is ··null!(ConstantExpr)) {
            // Combine Indices - If the source pointer to this getelementptr instruction
            // is a getelementptr instruction, combine the indices of the two
            // getelementptr instructions into a single instruction.
            //
            if (CE.Opc == InstructionKind_.GetElementPtr) {
                GetElementPtrConstantExpr GEP = (cast(GetElementPtrConstantExpr)(CE));
                Constant C2 = CFold_.s·foldGEPOfGEP(GEP, PointeeTy, InBounds, Idxs);
                if (C2 !is ··null!(Constant)) {
                    return C2;
                }
            }
            // Attempt to fold casts to the same type away.  For example, folding:
            //
            //   i32* getelementptr ([2 x i32]* bitcast ([3 x i32]* %X to [2 x i32]*),
            //                       i64 0, i64 0)
            // into:
            //
            //   i32* getelementptr ([3 x i32]* %X, i64 0, i64 0)
            //
            // Don't fold 如果 the cast_ is changing address spaces.
            if (CExp_.s·isCast(CE) && Idxs.length > 1 && .isNullValue(Idx0)) {
                指针类型_ SrcPtrTy = .cast_!(指针类型_)(CE.Ops[0].类型);
                指针类型_ DstPtrTy = .cast_!(指针类型_)(CE.类型);
                if ((SrcPtrTy !is ··null!(指针类型_)) && (DstPtrTy !is ··null!(指针类型_))) {
                    数组类型_ SrcArrayTy = .cast_!(数组类型_)(SrcPtrTy.类型);
                    数组类型_ DstArrayTy = .cast_!(数组类型_)(DstPtrTy.类型);
                    if ((SrcArrayTy !is ··null!(数组类型_)) && (DstArrayTy !is ··null!(数组类型_)) && SrcArrayTy.元素类型 == DstArrayTy.元素类型 && SrcPtrTy.地址 == DstPtrTy.地址) {
                        return CEGet_.s·getGetElementPtr(SrcArrayTy, (cast(Constant)(CE.Ops[0])), Idxs, InBounds, InRangeIndex);
                    }
                }
            }
        }
        NewIdxs = 创建数组!(Constant)();
        Ty = PointeeTy;
        Prev = C.类型;
        Unknown = Idxs[0].种类 != ValueTy_.ConstantIntVal && !.isConstantDataVector(Idxs[0]);
        {
            for (int i = 1; i < Idxs.length; ++i) {
                数组类型_ STy;
                ConstantInt CI;
                ulong NumElements;
                Constant CurrIdx;
                Constant PrevIdx;
                bool IsCurrIdxVector;
                bool IsPrevIdxVector;
                bool UseVector;
                Constant Factor;
                Constant Div;
                long CommonExtendedWidth;
                类型_ ExtendedTy;
                if (Idxs[i].种类 != ValueTy_.ConstantIntVal && !.isConstantDataVector(Idxs[i])) {
                    // We don't know 如果 it's in range or not.
                    Unknown = true;
                    下个(i);
                    continue;
                }
                if (!.isConstantInt(Idxs[i - 1]) && !.isConstantDataVector(Idxs[i - 1])) {
                    // Skip 如果 the type of the previous index is not supported.
                    下个(i);
                    continue;
                }
                if (InRangeIndex != 0 && i == InRangeIndex + 1) {
                    // If an index is marked inrange, we cannot apply this canonicalization to
                    // the following index, as that will cause the inrange index to point to
                    // the wrong element.
                    下个(i);
                    continue;
                }
                if (.isStructType(Ty)) {
                    // The verify makes sure that GEPs into a struct are in range.
                    下个(i);
                    continue;
                }
                if (.isVectorType(Ty)) {
                    // There can be awkward padding in after a non-power of two vector.
                    Unknown = true;
                    下个(i);
                    continue;
                }
                STy = .cast_!(数组类型_)(Ty);
                CI = .cast_!(ConstantInt)(Idxs[i]);
                if (CI !is ··null!(ConstantInt)) {
                    if (.isIndexInRangeOfArrayType(STy.数量, CI)) {
                        // It's in range, skip to the next index.
                        下个(i);
                        continue;
                    }
                    if (CI.Val.getSExtValue() < 0) {
                        // It's out of range and negative, don't try to factor it.
                        Unknown = true;
                        下个(i);
                        continue;
                    }
                }
                else {
                    ConstantDataVector CV = .cast_!(ConstantDataVector)(Idxs[i]);
                    bool InRange = true;
                    {
                        for (int I = 0; I < CDS_.s·getNumElements(CV); ++I) {
                            CI = .cast_!(ConstantInt)(CDS_.s·getElementAsConstant(CV, I));
                            InRange &= .isIndexInRangeOfArrayType(STy.数量, CI);
                            if (CI.Val.getSExtValue() < 0) {
                                Unknown = true;
                                break;
                            }
                        }
                    }
                    if (InRange || Unknown) {
                        // It's in range, skip to the next index.
                        // It's out of range and negative, don't try to factor it.
                        下个(i);
                        continue;
                    }
                }
                if (.isStructType(Prev)) {
                    // It's out of range, but the prior dimension is a struct
                    // so we can't do anything about it.
                    Unknown = true;
                    下个(i);
                    continue;
                }
                NewIdxs.length = Idxs.length;
                NumElements = STy.数量;
                CurrIdx = .cast_!(Constant)(Idxs[i]);
                PrevIdx = NewIdxs[i - 1] ? NewIdxs[i - 1] : .cast_!(Constant)(Idxs[i - 1]);
                IsCurrIdxVector = .isVectorType(CurrIdx.类型);
                IsPrevIdxVector = .isVectorType(PrevIdx.类型);
                UseVector = IsCurrIdxVector || IsPrevIdxVector;
                if (!IsCurrIdxVector && IsPrevIdxVector) {
                    CurrIdx = CGet_.s·DataVector_getSplat(.cast_!(向量类型_)(PrevIdx.类型).数量, CurrIdx);
                }
                if (!IsPrevIdxVector && IsCurrIdxVector) {
                    PrevIdx = CGet_.s·DataVector_getSplat(.cast_!(向量类型_)(CurrIdx.类型).数量, PrevIdx);
                }
                Factor = CGet_.s·CInt_get(.getScalarType(CurrIdx.类型), NumElements, false);
                if (UseVector) {
                    Factor = CGet_.s·DataVector_getSplat(IsPrevIdxVector ? .cast_!(向量类型_)(PrevIdx.类型).数量 : .cast_!(向量类型_)(CurrIdx.类型).数量, Factor);
                }
                NewIdxs[i] = CEGet_.s·getSRem(CurrIdx, Factor);
                Div = CEGet_.s·getSDiv(CurrIdx, Factor, false);
                CommonExtendedWidth = 核心.最大(.getScalarSizeInBits(PrevIdx.类型), .getScalarSizeInBits(Div.类型));
                CommonExtendedWidth = 核心.最大(CommonExtendedWidth, 64u);
                ExtendedTy = TGet_.s·IntTy_get((cast(uint)(CommonExtendedWidth)));
                if (UseVector) {
                    ExtendedTy = TGet_.s·VTy_get(ExtendedTy, false, IsPrevIdxVector ? .cast_!(向量类型_)(PrevIdx.类型).数量 : .cast_!(向量类型_)(CurrIdx.类型).数量);
                }
                if (!.isIntOrIntVectorTy(PrevIdx.类型, (cast(uint)(CommonExtendedWidth)))) {
                    PrevIdx = CEGet_.s·getSExt(PrevIdx, ExtendedTy);
                }
                if (!.isIntOrIntVectorTy(Div.类型, (cast(uint)(CommonExtendedWidth)))) {
                    Div = CEGet_.s·getSExt(Div, ExtendedTy);
                }
                NewIdxs[i - 1] = CEGet_.s·getAdd(PrevIdx, Div, false, false);
                下个(i);
            }
        }
        // If we did any factoring, start over with the adjusted indices.
        if ((NewIdxs !is ··null!(Constant[])) && NewIdxs.length > 0) {
            {
                for (int i = 0; i < NewIdxs.length; ++i) {
                    if (NewIdxs[i] is ··null!(Constant)) {
                        NewIdxs[i] = .cast_!(Constant)(Idxs[i]);
                    }
                }
            }
            return CEGet_.s·getGetElementPtr(PointeeTy, C, (cast(Value[])(NewIdxs)), InBounds, InRangeIndex);
        }
        // If all indices are known integers and normalized, we can do a simple
        // check 循环 the "inbounds" property.
        if (!Unknown && !InBounds) {
            GlobalVariable GV = .cast_!(GlobalVariable)(C);
            if (GV !is ··null!(GlobalVariable)) {
                if (!.hasExternalWeakLinkage(GV) && .isInBoundsIndices(Idxs)) {
                    return CEGet_.s·getGetElementPtr(PointeeTy, C, Idxs, /*InBounds=*/ true, InRangeIndex);
                }
            }
        }
        return 返回零值!(Constant)();
    }
    static Constant s·ConstantFoldExtractElementInstruction(Constant Val, Constant Idx) {
        向量类型_ ValVTy = .cast_!(向量类型_)(Val.类型);
        // extractelt poison, C . poison
        // extractelt C, undef . poison
        if (.isPoisonValue(Val) || .isUndefValue(Idx)) {
            return CGet_.s·PoisonValue_get(ValVTy.元素类型);
        }
        // extractelt undef, C . undef
        if (.isUndefValue(Val)) {
            return CGet_.s·UndefValue_get(ValVTy.元素类型);
        }
        ConstantInt CIdx = .dyn_cast!(ConstantInt)(Idx);
        if (CIdx is ··null!(ConstantInt)) {
            return 返回零值!(Constant)();
        }
        向量类型_ ValFVTy = .dyn_cast!(向量类型_)(Val.类型);
        if ((ValFVTy !is ··null!(向量类型_)) && .isFixedVectorType(ValFVTy)) {
            // ee({w,x,y,z}, wrong_value) . poison
            if (CIdx.Val.uge(ValFVTy.数量)) {
                return CGet_.s·PoisonValue_get(ValFVTy.元素类型);
            }
        }
        // ee (gep (ptr, idx0, ...), idx) . gep (ee (ptr, idx), ee (idx0, idx), ...)
        ConstantExpr CE = .dyn_cast!(ConstantExpr)(Val);
        if (CE !is ··null!(ConstantExpr)) {
            GetElementPtrConstantExpr GEP = .dyn_cast!(GetElementPtrConstantExpr)(CE);
            if (GEP !is ··null!(GetElementPtrConstantExpr)) {
                Constant[] Ops = 创建数组!(Constant)();
                {
                    for (int i = 0; i < CE.Ops.length; ++i) {
                        Constant Op = (cast(Constant)(CE.Ops[i]));
                        if (.isVectorType(Op.类型)) {
                            Constant ScalarOp = CEGet_.s·getExtractElement(Op, Idx);
                            if (ScalarOp is ··null!(Constant)) {
                                return 返回零值!(Constant)();
                            }
                            .追加!(Constant)(Ops, ScalarOp);
                        }
                        else {
                            .追加!(Constant)(Ops, Op);
                        }
                    }
                }
                return CEGet_.s·getWithOperands(CE, Ops, ValVTy.元素类型, false, GEP.SrcElementTy);
            }
            else if (CE.Opc == InstructionKind_.InsertElement) {
                ConstantInt IEIdx = .dyn_cast!(ConstantInt)(CE.Ops[2]);
                if (IEIdx !is ··null!(ConstantInt)) {
                    if (APSInt_isSameValue(new APSInt_(IEIdx.Val), new APSInt_(CIdx.Val))) {
                        return (cast(Constant)(CE.Ops[1]));
                    }
                    else {
                        return CEGet_.s·getExtractElement((cast(Constant)(CE.Ops[0])), CIdx);
                    }
                }
            }
        }
        // Lane < Splat minimum vector width => extractelt Splat(x), Lane . x
        if (CIdx.Val.ult(VTy_.s·getElementCount(ValVTy).getKnownMinValue())) {
            Constant SplatVal = .getSplatValue(Val, false);
            if (SplatVal !is ··null!(Constant)) {
                return SplatVal;
            }
        }
        return .getAggregateElement(Val, (cast(uint)(CIdx.Val.getZExtValue())));
    }
    static Constant s·ConstantFoldSelectInstruction(Constant Cond, Constant V1, Constant V2) {
        bool delegate(Constant) NotPoison;
        ConstantVector CondV;
        ConstantExpr TrueVal;
        ConstantExpr FalseVal;
        // If the 真 or 假 value is undef, we can fold to the other value as
        // long as the other value isn't poison.
        bool NotPoison·func(Constant C) {
            if (.isPoisonValue(C)) {
                return false;
            }
            // TODO: We can analyze ConstExpr by opcode to determine 如果 there is any
            //       possibility of poison.
            if (.isConstantExpr(C)) {
                return false;
            }
            if (C.种类 == ValueTy_.ConstantIntVal || .isGlobalVariable(C) || .isConstantFP(C) || C.种类 == ValueTy_.ConstantPointerNullVal || .isFunction(C)) {
                return true;
            }
            if (.isVectorType(C.类型)) {
                return !.containsPoisonElement(C) && !.containsConstantExpression(C);
            }
            // TODO: Recursively analyze aggregates or other constants.
            return false;
        }
        NotPoison = &NotPoison·func;
        // Check 循环 i1 and vector 真/假 conditions.
        if (.isNullValue(Cond)) {
            return V2;
        }
        if (.isAllOnesValue(Cond)) {
            return V1;
        }
        CondV = .dyn_cast!(ConstantVector)(Cond);
        if (CondV !is ··null!(ConstantVector)) {
            类型_ V1VTy = CondV.类型;
            Constant[] Result = 创建数组!(Constant)();
            类型_ Ty = TGet_.s·IntTy_get(32);
            {
                for (int i = 0; i < (cast(向量类型_)(V1VTy)).数量; ++i) {
                    Constant V;
                    Constant V1Element = CEGet_.s·getExtractElement(V1, CGet_.s·CInt_get(Ty, i, false));
                    Constant V2Element = CEGet_.s·getExtractElement(V2, CGet_.s·CInt_get(Ty, i, false));
                    Cond = .cast_!(Constant)(CondV.Ops[i]);
                    if (.isPoisonValue(Cond)) {
                        V = CGet_.s·PoisonValue_get(V1Element.类型);
                    }
                    else if (V1Element == V2Element) {
                        V = V1Element;
                    }
                    else if (.isUndefValue(Cond)) {
                        V = .isUndefValue(V1Element) ? V1Element : V2Element;
                    }
                    else {
                        if (Cond.种类 != ValueTy_.ConstantIntVal) {
                            break;
                        }
                        V = .isNullValue(Cond) ? V2Element : V1Element;
                    }
                    .追加!(Constant)(Result, V);
                }
            }
            // If we were able to build the vector, 返回 it.
            if (Result.length == (cast(向量类型_)(V1VTy)).数量) {
                return CGet_.s·Vector_get(Result);
            }
        }
        if (.isPoisonValue(Cond)) {
            return CGet_.s·PoisonValue_get(V1.类型);
        }
        if (.isUndefValue(Cond)) {
            if (.isUndefValue(V1)) {
                return V1;
            }
            return V2;
        }
        if (V1 == V2) {
            return V1;
        }
        if (.isPoisonValue(V1)) {
            return V2;
        }
        if (.isPoisonValue(V2)) {
            return V1;
        }
        if (.isUndefValue(V1) && NotPoison(V2)) {
            return V2;
        }
        if (.isUndefValue(V2) && NotPoison(V1)) {
            return V1;
        }
        TrueVal = .dyn_cast!(ConstantExpr)(V1);
        if (TrueVal !is ··null!(ConstantExpr)) {
            if (TrueVal.Opc == InstructionKind_.Select) {
                if (TrueVal.Ops[0] == Cond) {
                    return CEGet_.s·getSelect(Cond, (cast(Constant)(TrueVal.Ops[1])), V2);
                }
            }
        }
        FalseVal = .dyn_cast!(ConstantExpr)(V2);
        if (FalseVal !is ··null!(ConstantExpr)) {
            if (FalseVal.Opc == InstructionKind_.Select) {
                if (FalseVal.Ops[0] == Cond) {
                    return CEGet_.s·getSelect(Cond, V1, (cast(Constant)(FalseVal.Ops[2])));
                }
            }
        }
        return 返回零值!(Constant)();
    }
    static Constant s·ConstantFoldShuffleVectorInstruction(Constant V1, Constant V2, int[] Mask) {
        向量类型_ V1VTy = .cast_!(向量类型_)(V1.类型);
        uint MaskNumElts = (cast(uint)(Mask.length));
        ElementCount MaskEltCount = new ElementCount(MaskNumElts, .isScalableVectorType(V1VTy));
        类型_ EltTy = V1VTy.元素类型;
        // Undefined shuffle mask . undefined value.
        if (每个数组成员!(int)(Mask, (int Elt, size_t _) { return Elt == -1; })) {
            return CGet_.s·UndefValue_get(TGet_.s·VTy_get(EltTy, false, MaskNumElts));
        }
        // If the mask is all zeros this is a splat, no need to go through all
        // elements.
        if (每个数组成员!(int)(Mask, (int Elt, size_t _) { return Elt == 0; }) && !MaskEltCount.isScalable()) {
            整数类型_ Ty = TGet_.s·IntTy_get(32);
            Constant Elt = CEGet_.s·getExtractElement(V1, CGet_.s·CInt_get(Ty, 0, false));
            return CGet_.s·Vector_getSplat(MaskEltCount, Elt);
        }
        // Do not iterate on scalable vector. The num of elements is unknown at
        // compile-time.
        if (.isScalableVectorType(V1VTy)) {
            return 返回零值!(Constant)();
        }
        uint SrcNumElts = VTy_.s·getElementCount(V1VTy).getKnownMinValue();
        // Loop over the shuffle mask, evaluating each element.
        Constant[] Result = 创建数组!(Constant)();
        {
            for (int i = 0; i != MaskNumElts; ++i) {
                int Elt = Mask[i];
                if (Elt == -1) {
                    .追加!(Constant)(Result, CGet_.s·UndefValue_get(EltTy));
                    continue;
                }
                Constant InElt;
                if ((cast(uint)(Elt)) >= SrcNumElts * 2) {
                    InElt = CGet_.s·UndefValue_get(EltTy);
                }
                else if ((cast(uint)(Elt)) >= SrcNumElts) {
                    整数类型_ Ty = TGet_.s·IntTy_get(32);
                    InElt = CEGet_.s·getExtractElement(V2, CGet_.s·CInt_get(Ty, Elt - SrcNumElts, false));
                }
                else {
                    整数类型_ Ty = TGet_.s·IntTy_get(32);
                    InElt = CEGet_.s·getExtractElement(V1, CGet_.s·CInt_get(Ty, Elt, false));
                }
                .追加!(Constant)(Result, InElt);
            }
        }
        return CGet_.s·Vector_get(Result);
    }
    static Constant s·ConstantFoldInsertElementInstruction(Constant Val, Constant Elt, Constant Idx) {
        if (.isUndefValue(Idx)) {
            return CGet_.s·PoisonValue_get(Val.类型);
        }
        ConstantInt CIdx = .dyn_cast!(ConstantInt)(Idx);
        if (CIdx is ··null!(ConstantInt)) {
            return 返回零值!(Constant)();
        }
        // Do not iterate on scalable vector. The num of elements is unknown at
        // compile-time.
        if (.isScalableVectorType(Val.类型)) {
            return 返回零值!(Constant)();
        }
        向量类型_ ValTy = .cast_!(向量类型_)(Val.类型);
        uint NumElts = ValTy.数量;
        if (CIdx.Val.uge(NumElts)) {
            return CGet_.s·PoisonValue_get(Val.类型);
        }
        Constant[] Result = 创建数组!(Constant)();
        Result.length = NumElts;
        整数类型_ Ty = TGet_.s·IntTy_get(32);
        ulong IdxVal = CIdx.Val.getZExtValue();
        {
            for (int i = 0; i != NumElts; ++i) {
                if (i == IdxVal) {
                    .追加!(Constant)(Result, Elt);
                    continue;
                }
                Constant C = CEGet_.s·getExtractElement(Val, CGet_.s·CInt_get(Ty, i, false));
                .追加!(Constant)(cast(Constant[])(Result), C);
            }
        }
        return CGet_.s·Vector_get(Result);
    }
    static Constant s·ConstantFoldExtractValueInstruction(Constant Agg, uint[] Idxs) {
        // Base 若是: no indices, so 返回 the entire value.
        if ((Idxs is ··null!(uint[])) || Idxs.length == 0) {
            return Agg;
        }
        Constant C = .getAggregateElement(Agg, Idxs[0]);
        if (C !is ··null!(Constant)) {
            return CFold_.s·ConstantFoldExtractValueInstruction(C, Idxs[1 .. $]);
        }
        return 返回零值!(Constant)();
    }
    static Constant s·ConstantFoldInsertValueInstruction(Constant Agg, Constant Val, uint[] Idxs) {
        // Base 若是: no indices, so replace the entire value.
        if ((Idxs is ··null!(uint[])) || Idxs.length == 0) {
            return Val;
        }
        ulong NumElts = 0;
        结构类型_ ST = .dyn_cast!(结构类型_)(Agg.类型);
        if (ST !is ··null!(结构类型_)) {
            NumElts = ST_.s·getNumElements(ST);
        }
        else {
            NumElts = .cast_!(数组类型_)(Agg.类型).数量;
        }
        Constant[] Result = 创建数组!(Constant)();
        {
            for (int i = 0; i != NumElts; ++i) {
                Constant C = .getAggregateElement(Agg, i);
                if (C is ··null!(Constant)) {
                    return 返回零值!(Constant)();
                }
                if (Idxs[0] == i) {
                    C = CFold_.s·ConstantFoldInsertValueInstruction(C, Val, Idxs[1 .. $]);
                }
                .追加!(Constant)(Result, C);
            }
        }
        ST = .dyn_cast!(结构类型_)(Agg.类型);
        if (ST !is ··null!(结构类型_)) {
            return CGet_.s·Struct_get(ST, Result);
        }
        return CGet_.s·Array_get(.cast_!(数组类型_)(Agg.类型), Result);
    }
    static Constant s·ConstantFoldUnaryInstruction(uint Opcode, Constant C) {
        assert(Opcode >= InstructionKind_.UnaryOpsBegin && Opcode < InstructionKind_.UnaryOpsEnd, "Non-unary instruction detected"c);
        // Handle scalar UndefValue and scalable vector UndefValue. Fixed-length
        // vectors are always evaluated per element.
        bool IsScalableVector = .isScalableVectorType(C.类型);
        bool HasScalarUndefOrScalableVectorUndef = (!.isVectorType(C.类型) || IsScalableVector) && .isUndefValue(C);
        if (HasScalarUndefOrScalableVectorUndef) {
            switch (Opcode) {
                case InstructionKind_.FNeg: {
                    return // -undef . undef
                     C;
                } // -undef . undef
                case InstructionKind_.UnaryOpsEnd: {
                    assert(false, "Invalid UnaryOp"c);
                }
                default: break;
            }
        }
        // Constant should not be UndefValue, unless these are vector constants.
        assert(!HasScalarUndefOrScalableVectorUndef, "Unexpected UndefValue"c);
        // We only have FP UnaryOps right now.
        assert(!.isConstantInt(C), "Unexpected Integer UnaryOp"c);
        ConstantFP CFP = .dyn_cast!(ConstantFP)(C);
        if (CFP !is ··null!(ConstantFP)) {
            APFloat_ CV = CFP.Val;
            switch (Opcode) {
                case InstructionKind_.FNeg: {
                    CV.changeSign();
                    return CGet_.s·CFP_get(CV);
                }
                default: {
                    break;
                }
            }
        }
        else if (.isFixedVectorType(C.类型)) {
            向量类型_ VTy = .dyn_cast!(向量类型_)(C.类型);
            整数类型_ Ty = TGet_.s·IntTy_get(32);
            // Fast path 循环 splatted constants.
            Constant Splat = .getSplatValue(C, false);
            if (Splat !is ··null!(Constant)) {
                Constant Elt = CEGet_.s·get(Opcode, Splat);
                return CGet_.s·Vector_getSplat(VTy_.s·getElementCount(VTy), Elt);
            }
            // Fold each element and create a vector constant from those constants.
            Constant[] Result = 创建数组!(Constant)();
            {
                for (uint i = 0; i < VTy.数量; ++i) {
                    Constant ExtractIdx = CGet_.s·CInt_get(Ty, i, false);
                    Constant Elt = CEGet_.s·getExtractElement(C, ExtractIdx);
                    .追加!(Constant)(cast(Constant[])(Result), CEGet_.s·get(Opcode, Elt));
                }
            }
            return CGet_.s·Vector_get(Result);
        }
        // We don't know how to fold this.
        return ··null!(Constant);
    }
    static Constant s·ConstantFoldBinaryInstruction(uint Opcode, Constant C1, Constant C2) {
        assert(CExp_.s·isBinaryOp(Opcode), "Non-binary instruction detected"c);
        // Simplify BinOps with their identity values first. They are no-ops and we
        // can always 返回 the other value, including undef or poison values.
        // FIXME: remove unnecessary duplicated identity patterns below.
        // FIXME: Use AllowRHSConstant with getBinOpIdentity to handle additional ops,
        //        like X << 0 = X.
        Constant Identity = CExp_.s·getBinOpIdentity(Opcode, C1.类型, false);
        if (Identity !is ··null!(Constant)) {
            if (C1 == Identity) {
                return C2;
            }
            if (C2 == Identity) {
                return C1;
            }
        }
        // Binary operations propagate poison.
        if (.isPoisonValue(C1) || .isPoisonValue(C2)) {
            return CGet_.s·PoisonValue_get(C1.类型);
        }
        // Handle scalar UndefValue and scalable vector UndefValue. Fixed-length
        // vectors are always evaluated per element.
        bool IsScalableVector = .isScalableVectorType(C1.类型);
        bool HasScalarUndefOrScalableVectorUndef = (!.isVectorType(C1.类型) || IsScalableVector) && (.isUndefValue(C1) || .isUndefValue(C2));
        if (HasScalarUndefOrScalableVectorUndef) {
            switch (Opcode) {
                case InstructionKind_.Xor: {
                    if (.isUndefValue(C1) && .isUndefValue(C2)) {
                        // Handle undef ^ undef . 0 special 若是. This is a common
                        // idiom (misuse).
                        return CGet_.s·getNullValue(C1.类型);
                    }
                }
                // 贯穿
                case InstructionKind_.Add:
                case InstructionKind_.Sub: {
                    return CGet_.s·UndefValue_get(C1.类型);
                }
                case InstructionKind_.And: {
                    if (.isUndefValue(C1) && .isUndefValue(C2)) // undef & undef . undef
                     {
                        return C1;
                    }
                    return CGet_.s·getNullValue(C1.类型);
                } // undef & X . 0
                case InstructionKind_.Mul: // undef & X . 0
                {
                    // undef * undef . undef
                    if (.isUndefValue(C1) && .isUndefValue(C2)) {
                        return C1;
                    }
                    APInt_ CV;
                    // X * undef . undef   如果 X is odd
                    if (.match(C1, .m_APInt(&CV)) || .match(C2, .m_APInt(&CV))) { }
                    // X * undef . 0       otherwise
                    return CGet_.s·getNullValue(C1.类型);
                }
                case InstructionKind_.SDiv:
                case InstructionKind_.UDiv: {
                    // X / undef . poison
                    // X / 0 . poison
                    if (.match(C2, .m_CombineOr(.m_Undef(), .m_Zero()))) {
                        return CGet_.s·PoisonValue_get(C2.类型);
                    }
                    // undef / 1 . undef
                    if (.match(C2, .m_One())) {
                        return C1;
                    }
                    // undef / X . 0       otherwise
                    return CGet_.s·getNullValue(C1.类型);
                }
                case InstructionKind_.URem:
                case InstructionKind_.SRem: {
                    // X % undef . poison
                    // X % 0 . poison
                    if (.match(C2, .m_CombineOr(.m_Undef(), .m_Zero()))) {
                        return CGet_.s·PoisonValue_get(C2.类型);
                    }
                    // undef % X . 0       otherwise
                    return CGet_.s·getNullValue(C1.类型);
                }
                case InstructionKind_.Or: {
                    if (.isUndefValue(C1) && .isUndefValue(C2)) // undef | undef . undef
                     {
                        return C1;
                    }
                    return .getAllOnesValue(C1.类型);
                } // undef | X . ~0
                case InstructionKind_.LShr: {
                    // X >>l undef . poison
                    if (.isUndefValue(C2)) {
                        return CGet_.s·PoisonValue_get(C2.类型);
                    }
                    // undef >>l 0 . undef
                    if (.match(C2, .m_Zero())) {
                        return C1;
                    }
                    // undef >>l X . 0
                    return CGet_.s·getNullValue(C1.类型);
                }
                case InstructionKind_.AShr: {
                    // X >>a undef . poison
                    if (.isUndefValue(C2)) {
                        return CGet_.s·PoisonValue_get(C2.类型);
                    }
                    // undef >>a 0 . undef
                    if (.match(C2, .m_Zero())) {
                        return C1;
                    }
                    // TODO: undef >>a X . poison 如果 the shift is exact
                    // undef >>a X . 0
                    return CGet_.s·getNullValue(C1.类型);
                }
                case InstructionKind_.Shl: {
                    // X << undef . undef
                    if (.isUndefValue(C2)) {
                        return CGet_.s·PoisonValue_get(C2.类型);
                    }
                    // undef << 0 . undef
                    if (.match(C2, .m_Zero())) {
                        return C1;
                    }
                    // undef << X . 0
                    return CGet_.s·getNullValue(C1.类型);
                }
                case InstructionKind_.FSub: {
                    // -0.0 - undef -. undef (consistent with "fneg undef")
                    if (.match(C1, .m_NegZeroFP()) && .isUndefValue(C2)) {
                        return C2;
                    }
                }
                // 贯穿
                case InstructionKind_.FAdd:
                case InstructionKind_.FMul:
                case InstructionKind_.FDiv:
                case InstructionKind_.FRem: {
                    // [any flop] undef, undef . undef
                    if (.isUndefValue(C1) && .isUndefValue(C2)) {
                        return C1;
                    }
                    // [any flop] C, undef . NaN
                    // [any flop] undef, C . NaN
                    // We could potentially specialize NaN/Inf constants vs. 'normal'
                    // constants (possibly differently depending on opcode and operand). This
                    // would allow returning undef sometimes. But it is always safe to fold to
                    // NaN because we can choose the undef operand as NaN, and any FP opcode
                    // with a NaN operand will propagate NaN.
                    return CGet_.s·CFP_getNaN(C1.类型, false, 0);
                }
                case InstructionKind_.BinaryOpsEnd: {
                    assert(false, "Invalid BinaryOp"c);
                }
                default: break;
            }
        }
        // Neither constant should be UndefValue, unless these are vector constants.
        assert((!HasScalarUndefOrScalableVectorUndef), "Unexpected UndefValue"c);
        // Handle simplifications when the RHS is a constant int.
        ConstantInt CI2 = .dyn_cast!(ConstantInt)(C2);
        if (CI2 !is ··null!(ConstantInt)) {
            switch (Opcode) {
                case InstructionKind_.Add: {
                    if (CI2.Val.isZero()) {
                        return C1;
                    } // X + 0 == X
                    break;
                }
                case InstructionKind_.Sub: {
                    if (CI2.Val.isZero()) {
                        return C1;
                    } // X - 0 == X
                    break;
                }
                case InstructionKind_.Mul: {
                    if (CI2.Val.isZero()) {
                        return C2;
                    } // X * 0 == 0
                    if (CI2.Val.isOne()) {
                        return C1;
                    } // X * 1 == X
                    break;
                }
                case InstructionKind_.UDiv:
                case InstructionKind_.SDiv: {
                    if (CI2.Val.isOne()) {
                        return C1;
                    } // X / 1 == X
                    if (CI2.Val.isZero()) {
                        return CGet_.s·PoisonValue_get(CI2.类型);
                    } // X / 0 == poison
                    break;
                }
                case InstructionKind_.URem:
                case InstructionKind_.SRem: {
                    if (CI2.Val.isOne()) {
                        return CGet_.s·getNullValue(CI2.类型);
                    } // X % 1 == 0
                    if (CI2.Val.isZero()) {
                        return CGet_.s·PoisonValue_get(CI2.类型);
                    } // X % 0 == poison
                    break;
                }
                case InstructionKind_.And: {
                    if (CI2.Val.isZero()) {
                        return C2;
                    } // X & 0 == 0
                    if (CI2.Val.isAllOnesValue()) {
                        return C1;
                    } // X & -1 == X
                    ConstantExpr CE1 = .dyn_cast!(ConstantExpr)(C1);
                    if (CE1 !is ··null!(ConstantExpr)) {
                        // (zext i32 to i64) & 4294967295 . (zext i32 to i64)
                        if (CE1.Opc == InstructionKind_.ZExt) {
                            uint DstWidth = CI2.类型.位数;
                            uint SrcWidth = (cast(uint)(.getPrimitiveSizeInBits(CE1.Ops[0].类型).getFixedSize()));
                            APInt_ PossiblySetBits = new APInt_(APInt_getLowBitsSet(DstWidth, SrcWidth));
                            if ((PossiblySetBits.Op且等(CI2.Val)).Op等等(PossiblySetBits)) {
                                return C1;
                            }
                        }
                        // If and'ing the address of a global with a constant, fold it.
                        if (CE1.Opc == InstructionKind_.PtrToInt && .isGlobalValue(CE1.Ops[0])) {
                            GlobalValue GV = .cast_!(GlobalValue)(CE1.Ops[0]);
                            Align_ GVAlign;
                            Module TheModule = .有解析值!(Module)(GV.符号.值声明.父节点);
                            if (TheModule !is ··null!(Module)) {
                                DataLayout DL = TheModule.DL;
                                GVAlign = .getPointerAlignment(GV, DL);
                                // If the function alignment is not specified then assume that it
                                // is 4.
                                // This is dangerous; on x86, the alignment of the pointer
                                // corresponds to the alignment of the function, but might be less
                                // than 4 如果 it isn't explicitly specified.
                                // However, a fix 循环 this behaviour was reverted because it
                                // increased code size (see https://reviews.llvm.org/D55115)
                                // FIXME: This code should be deleted once existing targets have
                                // appropriate defaults
                                if (.isFunction(GV) && (DL.getFunctionPtrAlign() is ··null!(Align_))) {
                                    GVAlign = new Align_(4);
                                }
                            }
                            else if (.isGlobalVariable(GV)) {
                                GVAlign = .cast_!(GlobalVariable)(GV).Align;
                            }
                            if ((GVAlign !is ··null!(Align_)) && GVAlign.value() > 1) {
                                uint DstWidth = CI2.类型.位数;
                                uint SrcWidth = (cast(uint)(核心.最小((cast(ulong)(DstWidth)), (cast(ulong)(GVAlign.ShiftValue)))));
                                APInt_ BitsNotSet = new APInt_(APInt_getLowBitsSet(DstWidth, SrcWidth));
                                // If checking bits we know are clear, 返回 zero.
                                if ((CI2.Val.Op且等(BitsNotSet)).Op等等(CI2.Val)) {
                                    return CGet_.s·getNullValue(CI2.类型);
                                }
                            }
                        }
                    }
                    break;
                }
                case InstructionKind_.Or: {
                    if (CI2.Val.isZero()) {
                        return C1;
                    } // X | 0 == X
                    if (CI2.Val.isMinusOne()) {
                        return C2;
                    } // X | -1 == -1
                    break;
                }
                case InstructionKind_.Xor: {
                    if (CI2.Val.isZero()) {
                        return C1;
                    } // X ^ 0 == X
                    ConstantExpr CE1 = .dyn_cast!(ConstantExpr)(C1);
                    if (CE1 !is ··null!(ConstantExpr)) {
                        switch (CE1.Opc) {
                            case InstructionKind_.ICmp:
                            case InstructionKind_.FCmp: {
                                // cmp pred ^ 真 . cmp !pred
                                assert(CI2.Val.isOne(), "不是 1"c);
                                ubyte pred = .getPredicate((cast(CompareConstantExpr)(CE1)));
                                CmpInst_Predicate_ pred_p = CmpInst_.s·getInversePredicate(.转换枚举!(CmpInst_Predicate_)(pred));
                                return CEGet_.s·getCompare(pred_p, (cast(Constant)(CE1.Ops[0])), (cast(Constant)(CE1.Ops[1])), false);
                            }
                            default: {
                                break;
                            }
                        }
                    }
                    break;
                }
                case InstructionKind_.AShr: {
                    // ashr (zext C to Ty), C2 . lshr (zext C, CSA), C2
                    ConstantExpr CE1 = .dyn_cast!(ConstantExpr)(C1);
                    if (CE1 !is ··null!(ConstantExpr)) { }
                    break;
                }
                default: break;
            }
        }
        else if (.isConstantInt(C1)) {
            // If C1 is a ConstantInt and C2 is not, swap the operands.
            if (CExp_.s·isCommutative(Opcode)) {
                return CEGet_.s·get(Opcode, C2, C1);
            }
        }
        ConstantInt CI1 = .dyn_cast!(ConstantInt)(C1);
        if (CI1 !is ··null!(ConstantInt)) {
            CI2 = .dyn_cast!(ConstantInt)(C2);
            if (CI2 !is ··null!(ConstantInt)) {
                APInt_ C1V = CI1.Val;
                APInt_ C2V = CI2.Val;
                switch (Opcode) {
                    case InstructionKind_.Add: {
                        return CGet_.s·CInt_get(C1V.Op加等(C2V));
                    }
                    case InstructionKind_.Sub: {
                        return CGet_.s·CInt_get(C1V.Op减等(C2V));
                    }
                    case InstructionKind_.Mul: {
                        return CGet_.s·CInt_get(C1V.Op乘(C2V));
                    }
                    case InstructionKind_.UDiv: {
                        assert(!CI2.Val.isZero(), "Div by zero handled above"c);
                        return CGet_.s·CInt_get(C1V.udiv(C2V));
                    }
                    case InstructionKind_.SDiv: {
                        assert(!CI2.Val.isZero(), "Div by zero handled above"c);
                        if (C2V.isAllOnesValue() && C1V.isMinSignedValue()) {
                            return CGet_.s·PoisonValue_get(CI1.类型);
                        } // MIN_INT / -1 . poison
                        return CGet_.s·CInt_get(C1V.sdiv(C2V));
                    }
                    case InstructionKind_.URem: {
                        assert(!CI2.Val.isZero(), "Div by zero handled above"c);
                        return CGet_.s·CInt_get(C1V.urem(C2V));
                    }
                    case InstructionKind_.SRem: {
                        assert(!CI2.Val.isZero(), "Div by zero handled above"c);
                        if (C2V.isAllOnesValue() && C1V.isMinSignedValue()) {
                            return CGet_.s·PoisonValue_get(CI1.类型);
                        } // MIN_INT % -1 . poison
                        return CGet_.s·CInt_get(C1V.srem(C2V));
                    }
                    case InstructionKind_.And: {
                        return CGet_.s·CInt_get(C1V.Op且等(C2V));
                    }
                    case InstructionKind_.Or: {
                        return CGet_.s·CInt_get(C1V.Op或等(C2V));
                    }
                    case InstructionKind_.Xor: {
                        return CGet_.s·CInt_get(C1V.Op异或等(C2V));
                    }
                    case InstructionKind_.Shl: {
                        if (C2V.ult(C1V.getBitWidth())) {
                            return CGet_.s·CInt_get(C1V.shl(C2V));
                        }
                        return CGet_.s·PoisonValue_get(C1.类型);
                    } // too big shift is poison
                    case InstructionKind_.LShr: {
                        if (C2V.ult(C1V.getBitWidth())) {
                            return CGet_.s·CInt_get(C1V.lshr(C2V));
                        }
                        return CGet_.s·PoisonValue_get(C1.类型);
                    } // too big shift is poison
                    case InstructionKind_.AShr: {
                        if (C2V.ult(C1V.getBitWidth())) {
                            return CGet_.s·CInt_get(C1V.ashr(C2V));
                        }
                        return CGet_.s·PoisonValue_get(C1.类型);
                    } // too big shift is poison                            
                    default: {
                        break;
                    }
                }
            }
            switch (Opcode) {
                case InstructionKind_.SDiv:
                case InstructionKind_.UDiv:
                case InstructionKind_.URem:
                case InstructionKind_.SRem:
                case InstructionKind_.LShr:
                case InstructionKind_.AShr:
                case InstructionKind_.Shl: {
                    if (CI1.Val.isZero()) {
                        return C1;
                    }
                    break;
                }
                default: {
                    break;
                }
            }
        }
        else if (.dyn_cast!(ConstantFP)(C1) !is ··null!(ConstantFP)) {
            ConstantFP CFP1 = .dyn_cast!(ConstantFP)(C1);
            ConstantFP CFP2 = .dyn_cast!(ConstantFP)(C2);
            if (CFP2 !is ··null!(ConstantFP)) {
                APFloat_ C1V = CFP1.Val;
                APFloat_ C2V = CFP2.Val;
                APFloat_ C3V = C1V; // copy 循环 modification
                switch (Opcode) {
                    case InstructionKind_.FAdd: {
                        C3V.add(C2V, rmNearestTiesToEven);
                        return CGet_.s·CFP_get(C3V);
                    }
                    case InstructionKind_.FSub: {
                        C3V.subtract(C2V, rmNearestTiesToEven);
                        return CGet_.s·CFP_get(C3V);
                    }
                    case InstructionKind_.FMul: {
                        C3V.multiply(C2V, rmNearestTiesToEven);
                        return CGet_.s·CFP_get(C3V);
                    }
                    case InstructionKind_.FDiv: {
                        C3V.divide(C2V, rmNearestTiesToEven);
                        return CGet_.s·CFP_get(C3V);
                    }
                    case InstructionKind_.FRem: {
                        C3V.mod(C2V);
                        return CGet_.s·CFP_get(C3V);
                    }
                    default: {
                        break;
                    }
                }
            }
        }
        else if (.dyn_cast!(向量类型_)(C1.类型) !is ··null!(向量类型_)) {
            向量类型_ VTy = .dyn_cast!(向量类型_)(C1.类型);
            // Fast path 循环 splatted constants.
            Constant C2Splat = .getSplatValue(C2, false);
            if (C2Splat !is ··null!(Constant)) {
                if (CExp_.s·isIntDivRem(Opcode) && .isNullValue(C2Splat)) {
                    return CGet_.s·PoisonValue_get(VTy);
                }
                Constant C1Splat = .getSplatValue(C1, false);
                if (C1Splat !is ··null!(Constant)) {
                    return CGet_.s·Vector_getSplat(VTy_.s·getElementCount(VTy), CEGet_.s·get(Opcode, C1Splat, C2Splat));
                }
            }
            if (.isFixedVectorType(VTy)) {
                向量类型_ FVTy = .dyn_cast!(向量类型_)(VTy);
                // Fold each element and create a vector constant from those constants.
                Constant[] Result = 创建数组!(Constant)();
                整数类型_ Ty = TGet_.s·IntTy_get(32);
                {
                    for (uint i = 0; i < FVTy.数量; ++i) {
                        Constant ExtractIdx = CGet_.s·CInt_get(Ty, i, false);
                        Constant LHS = CEGet_.s·getExtractElement(C1, ExtractIdx);
                        Constant RHS = CEGet_.s·getExtractElement(C2, ExtractIdx);
                        // If any element of a divisor vector is zero, the whole op is poison.
                        if (CExp_.s·isIntDivRem(Opcode) && .isNullValue(RHS)) {
                            return CGet_.s·PoisonValue_get(VTy);
                        }
                        .追加!(Constant)(Result, CEGet_.s·get(Opcode, LHS, RHS));
                    }
                }
                return CGet_.s·Vector_get(Result);
            }
        }
        ConstantExpr CE1 = .dyn_cast!(ConstantExpr)(C1);
        if (CE1 !is ··null!(ConstantExpr)) {
            // There are many possible foldings we could do here.  We should probably
            // at least fold add of a pointer with an integer into the appropriate
            // getelementptr.  This will improve alias analysis a bit.
            // Given ((a + b) + c), 如果 (b + c) folds to something interesting, 返回
            // (a + (b + c)).
            if (CExp_.s·isAssociative(Opcode) && CE1.Opc == Opcode) {
                Constant T = CEGet_.s·get(Opcode, (cast(Constant)(CE1.Ops[1])), C2);
                if (!.isConstantExpr(T) || .cast_!(ConstantExpr)(T).Opc != Opcode) {
                    return CEGet_.s·get(Opcode, (cast(Constant)(CE1.Ops[0])), T);
                }
            }
        }
        else if (.isConstantExpr(C2)) {
            // If C2 is a constant expr and C1 isn't, flop them around and fold the
            // other way 如果 possible.
            if (CExp_.s·isCommutative(Opcode)) {
                return CFold_.s·ConstantFoldBinaryInstruction(Opcode, C2, C1);
            }
        }
        // i1 can be simplified in many cases.
        if (.isIntegerTy(C1.类型, 1)) {
            switch (Opcode) {
                case InstructionKind_.Add:
                case InstructionKind_.Sub: {
                    return CEGet_.s·getXor(C1, C2);
                }
                case InstructionKind_.Mul: {
                    return CEGet_.s·getAnd(C1, C2);
                }
                case InstructionKind_.Shl:
                case InstructionKind_.LShr:
                case InstructionKind_.AShr: {
                    // We can assume that C2 == 0.  If it were one the result would be
                    // undefined because the shift value is as large as the bitwidth.
                    return C1;
                }
                case InstructionKind_.SDiv:
                case InstructionKind_.UDiv: {
                    // We can assume that C2 == 1.  If it were zero the result would be
                    // undefined through division by zero.
                    return C1;
                }
                case InstructionKind_.URem:
                case InstructionKind_.SRem: {
                    // We can assume that C2 == 1.  If it were zero the result would be
                    // undefined through division by zero.
                    return CGet_.s·CInt_getFalse();
                }
                default: {
                    break;
                }
            }
        }
        // We don't know how to fold this.
        return ··null!(Constant);
    }
    static Constant s·ConstantFoldCompareInstruction(uint pred, Constant C1, Constant C2) {
        类型_ ResultTy;
        向量类型_ VT = .dyn_cast!(向量类型_)(C1.类型);
        if (VT !is ··null!(向量类型_)) {
            ResultTy = TGet_.s·VTy_get(TGet_.s·IntTy_get(1), VTy_.s·getElementCount(VT));
        }
        else {
            ResultTy = TGet_.s·IntTy_get(1);
        }
        // Fold FCMP_FALSE/FCMP_TRUE unconditionally.
        if (pred == CmpInst_Predicate_.FCMP_FALSE) {
            return CGet_.s·getNullValue(ResultTy);
        }
        if (pred == CmpInst_Predicate_.FCMP_TRUE) {
            return .getAllOnesValue(ResultTy);
        }
        // Handle some degenerate cases first
        if (.isPoisonValue(C1) || .isPoisonValue(C2)) {
            return CGet_.s·PoisonValue_get(ResultTy);
        }
        if (.isUndefValue(C1) || .isUndefValue(C2)) {
            CmpInst_Predicate_ Predicate = .转换枚举!(CmpInst_Predicate_)(pred);
            bool isIntegerPredicate = CmpInst_.s·isIntPredicate(Predicate);
            // For EQ and NE, we can always pick a value 循环 the undef to make the
            // predicate pass or fail, so we can 返回 undef.
            // Also, 如果 both operands are undef, we can 返回 undef 循环 int comparison.
            if (CmpInst_.s·isEquality(Predicate) || (isIntegerPredicate && C1 == C2)) {
                return CGet_.s·UndefValue_get(ResultTy);
            }
            // Otherwise, 循环 integer compare, pick the same value as the non-undef
            // operand, and fold it to 真 or 假.
            if (isIntegerPredicate) {
                return CGet_.s·CInt_get(ResultTy, CmpInst_.s·isTrueWhenEqual(Predicate));
            }
            // Choosing NaN 循环 the undef will always make unordered comparison succeed
            // and ordered comparison fails.
            return CGet_.s·CInt_get(ResultTy, CmpInst_.s·isUnordered(Predicate));
        }
        // icmp eq/ne(null,GV) . 假/真
        if (.isNullValue(C1)) {
            GlobalValue GV = .dyn_cast!(GlobalValue)(C2);
            if (GV !is ··null!(GlobalValue)) { }
        }
        else if (.isNullValue(C2)) {
            GlobalValue GV = .dyn_cast!(GlobalValue)(C1);
            if (GV !is ··null!(GlobalValue)) {
                // Don't try to evaluate aliases.  External weak GV can be null.
                if (!.isGlobalAlias(GV) && !.hasExternalWeakLinkage(GV) && !.NullPointerIsDefined(返回零值!(Function)() /* F */, (cast(指针类型_)(GV.类型)).地址)) {
                    if (pred == CmpInst_Predicate_.ICMP_EQ) {
                        return CGet_.s·CInt_getFalse();
                    }
                    else if (pred == CmpInst_Predicate_.ICMP_NE) {
                        return CGet_.s·CInt_getTrue();
                    }
                }
            }
            // The caller is expected to commute the operands 如果 the constant expression
            // is C2.
            // C1 >= 0 -. 真
            if (pred == CmpInst_Predicate_.ICMP_UGE) {
                return .getAllOnesValue(ResultTy);
            }
            // C1 < 0 -. 假
            if (pred == CmpInst_Predicate_.ICMP_ULT) {
                return CGet_.s·getNullValue(ResultTy);
            }
        }
        // If the comparison is a comparison between two i1's, simplify it.
        if (.isIntegerTy(C1.类型, 1)) {
            switch (pred) {
                case CmpInst_Predicate_.ICMP_EQ: {
                    if (C2.种类 == ValueTy_.ConstantIntVal) {
                        return CEGet_.s·getXor(C1, CEGet_.s·getNot(C2));
                    }
                    return CEGet_.s·getXor(CEGet_.s·getNot(C1), C2);
                }
                case CmpInst_Predicate_.ICMP_NE: {
                    return CEGet_.s·getXor(C1, C2);
                }
                default: {
                    break;
                }
            }
        }
        if (C1.种类 == ValueTy_.ConstantIntVal && C2.种类 == ValueTy_.ConstantIntVal) {
            APInt_ V1 = .cast_!(ConstantInt)(C1).Val;
            APInt_ V2 = .cast_!(ConstantInt)(C2).Val;
            switch (pred) {
                case CmpInst_Predicate_.ICMP_EQ: {
                    return CGet_.s·CInt_get(ResultTy, V1 == V2);
                }
                case CmpInst_Predicate_.ICMP_NE: {
                    return CGet_.s·CInt_get(ResultTy, V1 != V2);
                }
                case CmpInst_Predicate_.ICMP_SLT: {
                    return CGet_.s·CInt_get(ResultTy, V1.slt(V2));
                }
                case CmpInst_Predicate_.ICMP_SGT: {
                    return CGet_.s·CInt_get(ResultTy, V1.sgt(V2));
                }
                case CmpInst_Predicate_.ICMP_SLE: {
                    return CGet_.s·CInt_get(ResultTy, V1.sle(V2));
                }
                case CmpInst_Predicate_.ICMP_SGE: {
                    return CGet_.s·CInt_get(ResultTy, V1.sge(V2));
                }
                case CmpInst_Predicate_.ICMP_ULT: {
                    return CGet_.s·CInt_get(ResultTy, V1.ult(V2));
                }
                case CmpInst_Predicate_.ICMP_UGT: {
                    return CGet_.s·CInt_get(ResultTy, V1.ugt(V2));
                }
                case CmpInst_Predicate_.ICMP_ULE: {
                    return CGet_.s·CInt_get(ResultTy, V1.ule(V2));
                }
                case CmpInst_Predicate_.ICMP_UGE: {
                    return CGet_.s·CInt_get(ResultTy, V1.uge(V2));
                }
                default: {
                    assert(false, "Invalid ICmp Predicate"c);
                    break;
                }
            }
        }
        else if (.isConstantFP(C1) && .isConstantFP(C2)) {
            APFloat_ C1V = .cast_!(ConstantFP)(C1).Val;
            APFloat_ C2V = .cast_!(ConstantFP)(C2).Val;
            APFloat_CmpResult_ R = C1V.compare(C2V);
            switch (pred) {
                case CmpInst_Predicate_.FCMP_FALSE: {
                    return CGet_.s·getNullValue(ResultTy);
                }
                case CmpInst_Predicate_.FCMP_TRUE: {
                    return .getAllOnesValue(ResultTy);
                }
                case CmpInst_Predicate_.FCMP_UNO: {
                    return CGet_.s·CInt_get(ResultTy, R == APFloat_CmpResult_.cmpUnordered);
                }
                case CmpInst_Predicate_.FCMP_ORD: {
                    return CGet_.s·CInt_get(ResultTy, R != APFloat_CmpResult_.cmpUnordered);
                }
                case CmpInst_Predicate_.FCMP_UEQ: {
                    return CGet_.s·CInt_get(ResultTy, R == APFloat_CmpResult_.cmpUnordered || R == APFloat_CmpResult_.cmpEqual);
                }
                case CmpInst_Predicate_.FCMP_OEQ: {
                    return CGet_.s·CInt_get(ResultTy, R == APFloat_CmpResult_.cmpEqual);
                }
                case CmpInst_Predicate_.FCMP_UNE: {
                    return CGet_.s·CInt_get(ResultTy, R != APFloat_CmpResult_.cmpEqual);
                }
                case CmpInst_Predicate_.FCMP_ONE: {
                    return CGet_.s·CInt_get(ResultTy, R == APFloat_CmpResult_.cmpLessThan || R == APFloat_CmpResult_.cmpGreaterThan);
                }
                case CmpInst_Predicate_.FCMP_ULT: {
                    return CGet_.s·CInt_get(ResultTy, R == APFloat_CmpResult_.cmpUnordered || R == APFloat_CmpResult_.cmpLessThan);
                }
                case CmpInst_Predicate_.FCMP_OLT: {
                    return CGet_.s·CInt_get(ResultTy, R == APFloat_CmpResult_.cmpLessThan);
                }
                case CmpInst_Predicate_.FCMP_UGT: {
                    return CGet_.s·CInt_get(ResultTy, R == APFloat_CmpResult_.cmpUnordered || R == APFloat_CmpResult_.cmpGreaterThan);
                }
                case CmpInst_Predicate_.FCMP_OGT: {
                    return CGet_.s·CInt_get(ResultTy, R == APFloat_CmpResult_.cmpGreaterThan);
                }
                case CmpInst_Predicate_.FCMP_ULE: {
                    return CGet_.s·CInt_get(ResultTy, R != APFloat_CmpResult_.cmpGreaterThan);
                }
                case CmpInst_Predicate_.FCMP_OLE: {
                    return CGet_.s·CInt_get(ResultTy, R == APFloat_CmpResult_.cmpLessThan || R == APFloat_CmpResult_.cmpEqual);
                }
                case CmpInst_Predicate_.FCMP_UGE: {
                    return CGet_.s·CInt_get(ResultTy, R != APFloat_CmpResult_.cmpLessThan);
                }
                case CmpInst_Predicate_.FCMP_OGE: {
                    return CGet_.s·CInt_get(ResultTy, R == APFloat_CmpResult_.cmpGreaterThan || R == APFloat_CmpResult_.cmpEqual);
                }
                default: {
                    assert(false, "Invalid FCmp Predicate"c);
                    break;
                }
            }
        }
        else if (.dyn_cast!(向量类型_)(C1.类型) !is ··null!(向量类型_)) {
            向量类型_ C1VTy = .dyn_cast!(向量类型_)(C1.类型);
            // Fast path 循环 splatted constants.
            Constant C1Splat = .getSplatValue(C1, false);
            if (C1Splat !is ··null!(Constant)) {
                Constant C2Splat = .getSplatValue(C2, false);
                if (C2Splat !is ··null!(Constant)) {
                    return CGet_.s·Vector_getSplat(VTy_.s·getElementCount(C1VTy), CEGet_.s·getCompare(pred, C1Splat, C2Splat, false));
                }
            }
            // Do not iterate on scalable vector. The number of elements is unknown at
            // compile-time.
            if (.isScalableVectorType(C1VTy)) {
                return 返回零值!(Constant)();
            }
            // If we can constant fold the comparison of each element, constant fold
            // the whole vector comparison.
            Constant[] ResElts = 创建数组!(Constant)();
            整数类型_ Ty = TGet_.s·IntTy_get(32);
            {
                // Compare the elements, producing an i1 result or constant expr.
                for (int I = 0; I < VTy_.s·getElementCount(C1VTy).getKnownMinValue(); ++I) {
                    Constant C1E = CEGet_.s·getExtractElement(C1, CGet_.s·CInt_get(Ty, I, false));
                    Constant C2E = CEGet_.s·getExtractElement(C2, CGet_.s·CInt_get(Ty, I, false));
                    .追加!(Constant)(cast(Constant[])(ResElts), CEGet_.s·getCompare(pred, C1E, C2E, false));
                }
            }
            return CGet_.s·Vector_get(ResElts);
        }
        if (.isFloatingPointTy(C1.类型) && (.isConstantExpr(C1) || .isConstantExpr(C2))) {
            int Result = -1; // -1 = unknown, 0 = known 假, 1 = known 真.
            CmpInst_Predicate_ pr = CmpInst_.s·evaluateFCmpRelation(C1, C2);
            switch (pr) {
                case CmpInst_Predicate_.FCMP_UNO:
                case CmpInst_Predicate_.FCMP_ORD:
                case CmpInst_Predicate_.FCMP_UNE:
                case CmpInst_Predicate_.FCMP_ULT:
                case CmpInst_Predicate_.FCMP_UGT:
                case CmpInst_Predicate_.FCMP_ULE:
                case CmpInst_Predicate_.FCMP_UGE:
                case CmpInst_Predicate_.FCMP_TRUE:
                case CmpInst_Predicate_.FCMP_FALSE:
                case CmpInst_Predicate_.BAD_FCMP_PREDICATE: {
                    break;
                } // Couldn't determine anything about these constants.
                case CmpInst_Predicate_.FCMP_OEQ: {
                    Result = (pred == CmpInst_Predicate_.FCMP_UEQ || pred == CmpInst_Predicate_.FCMP_OEQ || pred == CmpInst_Predicate_.FCMP_ULE || pred == CmpInst_Predicate_.FCMP_OLE || pred == CmpInst_Predicate_.FCMP_UGE || pred == CmpInst_Predicate_.FCMP_OGE) ? 1 : 0;
                    break;
                }
                case CmpInst_Predicate_.FCMP_OLT: {
                    Result = (pred == CmpInst_Predicate_.FCMP_UNE || pred == CmpInst_Predicate_.FCMP_ONE || pred == CmpInst_Predicate_.FCMP_ULT || pred == CmpInst_Predicate_.FCMP_OLT || pred == CmpInst_Predicate_.FCMP_ULE || pred == CmpInst_Predicate_.FCMP_OLE) ? 1 : 0;
                    break;
                }
                case CmpInst_Predicate_.FCMP_OGT: {
                    Result = (pred == CmpInst_Predicate_.FCMP_UNE || pred == CmpInst_Predicate_.FCMP_ONE || pred == CmpInst_Predicate_.FCMP_UGT || pred == CmpInst_Predicate_.FCMP_OGT || pred == CmpInst_Predicate_.FCMP_UGE || pred == CmpInst_Predicate_.FCMP_OGE) ? 1 : 0;
                    break;
                }
                case CmpInst_Predicate_.FCMP_OLE: {
                    // We can only partially decide this relation.
                    if (pred == CmpInst_Predicate_.FCMP_UGT || pred == CmpInst_Predicate_.FCMP_OGT) {
                        Result = 0;
                    }
                    else if (pred == CmpInst_Predicate_.FCMP_ULT || pred == CmpInst_Predicate_.FCMP_OLT) {
                        Result = 1;
                    }
                    break;
                }
                case CmpInst_Predicate_.FCMP_OGE: {
                    // We can only partially decide this relation.
                    if (pred == CmpInst_Predicate_.FCMP_ULT || pred == CmpInst_Predicate_.FCMP_OLT) {
                        Result = 0;
                    }
                    else if (pred == CmpInst_Predicate_.FCMP_UGT || pred == CmpInst_Predicate_.FCMP_OGT) {
                        Result = 1;
                    }
                    break;
                }
                case CmpInst_Predicate_.FCMP_ONE: {
                    // We can only partially decide this relation.
                    if (pred == CmpInst_Predicate_.FCMP_OEQ || pred == CmpInst_Predicate_.FCMP_UEQ) {
                        Result = 0;
                    }
                    else if (pred == CmpInst_Predicate_.FCMP_ONE || pred == CmpInst_Predicate_.FCMP_UNE) {
                        Result = 1;
                    }
                    break;
                }
                case CmpInst_Predicate_.FCMP_UEQ: {
                    // We can only partially decide this relation.
                    if (pred == CmpInst_Predicate_.FCMP_ONE) {
                        Result = 0;
                    }
                    else if (pred == CmpInst_Predicate_.FCMP_UEQ) {
                        Result = 1;
                    }
                    break;
                }
                default: {
                    assert(false, "Unknown relation!"c);
                    break;
                }
            }
            // If we evaluated the result, 返回 it now.
            if (Result != -1) {
                return CGet_.s·CInt_get(ResultTy, Result, false);
            }
        }
        else {
            // Evaluate the relation between the two constants, per the predicate.
            int Result = -1; // -1 = unknown, 0 = known 假, 1 = known 真.
            CmpInst_Predicate_ pr = CmpInst_.s·evaluateICmpRelation(C1, C2, CmpInst_.s·isSigned(.转换枚举!(CmpInst_Predicate_)(pred)));
            switch (pr) {
                case CmpInst_Predicate_.BAD_ICMP_PREDICATE: {
                    break // Couldn't determine anything about these constants.
                    ;
                } // Couldn't determine anything about these constants.
                case CmpInst_Predicate_.ICMP_EQ: {
                    // If we know the constants are equal, we can decide the result of this
                    // computation precisely.
                    Result = CmpInst_.s·isTrueWhenEqual(.转换枚举!(CmpInst_Predicate_)(pred)) ? 1 : 0;
                    break;
                }
                case CmpInst_Predicate_.ICMP_ULT: {
                    switch (pred) {
                        case CmpInst_Predicate_.ICMP_ULT:
                        case CmpInst_Predicate_.ICMP_NE:
                        case CmpInst_Predicate_.ICMP_ULE: {
                            Result = 1;
                            break;
                        }
                        case CmpInst_Predicate_.ICMP_UGT:
                        case CmpInst_Predicate_.ICMP_EQ:
                        case CmpInst_Predicate_.ICMP_UGE: {
                            Result = 0;
                            break;
                        }
                        default: break;
                    }
                    break;
                }
                case CmpInst_Predicate_.ICMP_SLT: {
                    switch (pred) {
                        case CmpInst_Predicate_.ICMP_SLT:
                        case CmpInst_Predicate_.ICMP_NE:
                        case CmpInst_Predicate_.ICMP_SLE: {
                            Result = 1;
                            break;
                        }
                        case CmpInst_Predicate_.ICMP_SGT:
                        case CmpInst_Predicate_.ICMP_EQ:
                        case CmpInst_Predicate_.ICMP_SGE: {
                            Result = 0;
                            break;
                        }
                        default: break;
                    }
                    break;
                }
                case CmpInst_Predicate_.ICMP_UGT: {
                    switch (pred) {
                        case CmpInst_Predicate_.ICMP_UGT:
                        case CmpInst_Predicate_.ICMP_NE:
                        case CmpInst_Predicate_.ICMP_UGE: {
                            Result = 1;
                            break;
                        }
                        case CmpInst_Predicate_.ICMP_ULT:
                        case CmpInst_Predicate_.ICMP_EQ:
                        case CmpInst_Predicate_.ICMP_ULE: {
                            Result = 0;
                            break;
                        }
                        default: break;
                    }
                    break;
                }
                case CmpInst_Predicate_.ICMP_SGT: {
                    switch (pred) {
                        case CmpInst_Predicate_.ICMP_SGT:
                        case CmpInst_Predicate_.ICMP_NE:
                        case CmpInst_Predicate_.ICMP_SGE: {
                            Result = 1;
                            break;
                        }
                        case CmpInst_Predicate_.ICMP_SLT:
                        case CmpInst_Predicate_.ICMP_EQ:
                        case CmpInst_Predicate_.ICMP_SLE: {
                            Result = 0;
                            break;
                        }
                        default: break;
                    }
                    break;
                }
                case CmpInst_Predicate_.ICMP_ULE: {
                    if (pred == CmpInst_Predicate_.ICMP_UGT) {
                        Result = 0;
                    }
                    if (pred == CmpInst_Predicate_.ICMP_ULT || pred == CmpInst_Predicate_.ICMP_ULE) {
                        Result = 1;
                    }
                    break;
                }
                case CmpInst_Predicate_.ICMP_SLE: {
                    if (pred == CmpInst_Predicate_.ICMP_SGT) {
                        Result = 0;
                    }
                    if (pred == CmpInst_Predicate_.ICMP_SLT || pred == CmpInst_Predicate_.ICMP_SLE) {
                        Result = 1;
                    }
                    break;
                }
                case CmpInst_Predicate_.ICMP_UGE: {
                    if (pred == CmpInst_Predicate_.ICMP_ULT) {
                        Result = 0;
                    }
                    if (pred == CmpInst_Predicate_.ICMP_UGT || pred == CmpInst_Predicate_.ICMP_UGE) {
                        Result = 1;
                    }
                    break;
                }
                case CmpInst_Predicate_.ICMP_SGE: {
                    if (pred == CmpInst_Predicate_.ICMP_SLT) {
                        Result = 0;
                    }
                    if (pred == CmpInst_Predicate_.ICMP_SGT || pred == CmpInst_Predicate_.ICMP_SGE) {
                        Result = 1;
                    }
                    break;
                }
                case CmpInst_Predicate_.ICMP_NE: {
                    if (pred == CmpInst_Predicate_.ICMP_EQ) {
                        Result = 0;
                    }
                    if (pred == CmpInst_Predicate_.ICMP_NE) {
                        Result = 1;
                    }
                    break;
                }
                default: {
                    assert(false, "Unknown relational!"c);
                    break;
                }
            }
            // If we evaluated the result, 返回 it now.
            if (Result != -1) {
                return CGet_.s·CInt_get(ResultTy, Result, false);
            }
            // If the right hand side is a bitcast, try using its inverse to simplify
            // it by moving it to the left hand side.  We can't do this 如果 it would turn
            // a vector compare into a scalar compare or visa versa, or 如果 it would turn
            // the operands into FP values.
            ConstantExpr CE2 = .dyn_cast!(ConstantExpr)(C2);
            if (CE2 !is ··null!(ConstantExpr)) {
                Constant CE2Op0 = (cast(Constant)(CE2.Ops[0]));
                if (CE2.Opc == InstructionKind_.BitCast && .isVectorType(CE2.类型) == .isVectorType(CE2Op0.类型) && !.isFPOrFPVectorTy(CE2Op0.类型)) {
                    Constant Inverse = CEGet_.s·getBitCast(C1, CE2Op0.类型);
                    return CEGet_.s·getICmp(pred, Inverse, CE2Op0);
                }
            }
            // If the left hand side is an extension, try eliminating it.
            ConstantExpr CE1 = .dyn_cast!(ConstantExpr)(C1);
            if (CE1 !is ··null!(ConstantExpr)) {
                if ((CE1.Opc == InstructionKind_.SExt && CmpInst_.s·isSigned(.转换枚举!(CmpInst_Predicate_)(pred))) || (CE1.Opc == InstructionKind_.ZExt && !CmpInst_.s·isSigned(.转换枚举!(CmpInst_Predicate_)(pred)))) {
                    Value CE1Op0 = CE1.Ops[0];
                    Constant CE1Inverse = CEGet_.s·getTrunc(CE1, CE1Op0.类型);
                    if (CE1Inverse == CE1Op0) {
                        // Check whether we can safely truncate the right hand side.
                        Constant C2Inverse = CEGet_.s·getTrunc(C2, CE1Op0.类型);
                        if (CEGet_.s·getCast(CE1.Opc, C2Inverse, C2.类型) == C2) {
                            return CEGet_.s·getICmp(pred, CE1Inverse, C2Inverse);
                        }
                    }
                }
            }
            if ((!.isConstantExpr(C1) && .isConstantExpr(C2)) || (.isNullValue(C1) && !.isNullValue(C2))) {
                // If C2 is a constant expr and C1 isn't, flip them around and fold the
                // other way 如果 possible.
                // Also, 如果 C1 is null and C2 isn't, flip them around.
                pred = CmpInst_.s·getSwappedPredicate(.转换枚举!(CmpInst_Predicate_)(pred));
                return CEGet_.s·getICmp(pred, C2, C1);
            }
        }
        return 返回零值!(Constant)();
    }
}
class CEGet_ {
    this() { }
    static ConstantExpr s·getOrCreate(类型_ Ty, ConstantExprKeyType V) {
        dstring 键 = .获取类型文本Id(Ty) ~ ":O:"d ~ ·to!(dstring)(V.toHash());
        if (ExprConstants.具有(键)) {
            return ExprConstants.获取(键);
        }
        ConstantExpr Exp = V.create(Ty);
        ExprConstants.p·设置(键, Exp);
        return ExprConstants.获取(键);
    }
    static Constant s·getFoldedCast(InstructionKind_ opc, Constant C, 类型_ Ty, bool OnlyIfReduced = false) {
        assert(.isFirstClassType(Ty), "Cannot cast_ to an aggregate type!"c);
        // Fold a few common cases
        Constant FC = CFold_.s·ConstantFoldCastInstruction(opc, C, Ty);
        if (FC !is ··null!(Constant)) {
            return FC;
        }
        if (OnlyIfReduced) {
            return ··null!(Constant);
        }
        // Look up the constant in the table first to ensure uniqueness.
        ConstantExprKeyType Key = new ConstantExprKeyType(opc, [C]);
        return CEGet_.s·getOrCreate(Ty, Key);
    }
    static Constant s·getExtractElement(Constant Val, Constant Idx, 类型_ OnlyIfReducedTy = ··null!(类型_)) {
        assert(.isVectorType(Val.类型), "Tried to create extractelement operation on non-vector type!"c);
        assert(.isIntegerTy(Idx.类型), "Extractelement index must be an integer type!"c);
        Constant FC = CFold_.s·ConstantFoldExtractElementInstruction(Val, Idx);
        if (FC !is ··null!(Constant)) {
            return FC;
        } // Fold a few common cases.
        类型_ ReqTy = (cast(向量类型_)(Val.类型)).元素类型;
        if (OnlyIfReducedTy == ReqTy) {
            return // Look up the constant in the table first to ensure uniqueness
             ··null!(Constant);
        }
        // Look up the constant in the table first to ensure uniqueness
        Constant[] ArgVec = [Val, Idx];
        ConstantExprKeyType Key = new ConstantExprKeyType(InstructionKind_.ExtractElement, ArgVec);
        return CEGet_.s·getOrCreate(ReqTy, Key);
    }
    static Constant s·getInBoundsGetElementPtr(类型_ Ty, Constant C, Value[] Idxs) {
        return CEGet_.s·getGetElementPtr(Ty, C, Idxs, true);
    }
    static Constant s·getGetElementPtr(类型_ Ty, Constant C, Value[] Idxs, bool InBounds, uint InRangeIndex = ··null!(uint), 类型_ OnlyIfReducedTy = ··null!(类型_)) {
        类型_ delegate(Object, 类型_) getIndexedType_n;
        指针类型_ OrigPtrTy;
        Constant FC;
        类型_ DestTy;
        uint AS;
        类型_ ReqTy;
        ElementCount EltCount;
        向量类型_ VecTy;
        Constant[] ArgVec;
        Object VTy;
        uint SubClassOptionalData;
        ConstantExprKeyType Key;
        类型_ getIndexedType_n·func(Object idx, 类型_ Ty) {
            类型_ T;
            T = (cast(类型_)(idx));
            if (T !is ··null!(类型_)) {
                return T;
            }
            return ST_.s·getTypeAtIndex((cast(结构类型_)(Ty)), (cast(Value)(idx)));
        }
        getIndexedType_n = &getIndexedType_n·func;
        OrigPtrTy = (cast(指针类型_)(.getScalarType(C.类型)));
        assert(Ty !is ··null!(类型_), "Must specify element type"c);
        assert(PTy_.s·isOpaqueOrPointeeTypeMatches(OrigPtrTy, Ty), "xx"c);
        FC = CFold_.s·ConstantFoldGetElementPtr(Ty, C, InBounds, InRangeIndex, Idxs);
        if (FC !is ··null!(Constant)) {
            return FC;
        } // Fold a few common cases.
        DestTy = GEP_.s·getIndexedType(Ty, (cast(Value[])(Idxs)));
        assert(DestTy !is ··null!(类型_), "GEP indices invalid!"c);
        AS = OrigPtrTy.地址;
        ReqTy = PTy_.s·isOpaque(OrigPtrTy) ? TGet_.s·PtrTy_get(返回零值!(类型_)(), AS) : TY_.s·getPointerTo(DestTy, AS);
        EltCount = ECFixed(0);
        VecTy = (cast(向量类型_)(C.类型));
        if (VecTy !is ··null!(向量类型_)) {
            EltCount = VTy_.s·getElementCount(VecTy);
        }
        else {
            foreach (Value Idx; Idxs) {
                VecTy = (cast(向量类型_)(Idx.类型));
                if (VecTy !is ··null!(向量类型_)) {
                    EltCount = VTy_.s·getElementCount(VecTy);
                }
            }
        }
        if (EltCount.isNonZero()) {
            ReqTy = TGet_.s·VTy_get(ReqTy, false, EltCount.getValue());
        }
        if (OnlyIfReducedTy == ReqTy) {
            return ··null!(Constant);
        }
        ArgVec = 创建数组!(Constant)();
        .追加!(Constant)(ArgVec, C);
        VTy = Ty;
        {
            for (int i = 0; i < Idxs.length; ++i) {
                Value Idx;
                Idx = Idxs[i];
                assert((!.isVectorType(Idx.类型) || VTy_.s·getElementCount((cast(向量类型_)(Idx.类型))).p·Op等等(EltCount)), "getelementptr index type missmatch"c);
                VTy = getIndexedType_n(Idx, Ty);
                类型_ ···temp·0·_2 = (cast(类型_)(VTy));
                类型_ ···temp·0·_3 = (cast(类型_)(VTy));
                if ((···temp·0·_2 !is ··null!(类型_)) && (cast(类型_)(VTy)).种类 == TypeID_.StructTyID && .isVectorType(Idx.类型)) {
                    Idx = .getSplatValue((cast(Constant)(Idx)), false);
                }
                else if (((VTy is ··null!(Object)) || (···temp·0·_3 is ··null!(类型_))) && EltCount.isNonZero() && !.isVectorType(Idx.类型)) {
                    Idx = CGet_.s·Vector_getSplat(EltCount, (cast(Constant)(Idx)));
                }
                .追加!(Constant)(ArgVec, (cast(Constant)(Idx)));
            }
        }
        SubClassOptionalData = InBounds ? 1 : 0;
        if ((InRangeIndex !is ··null!(uint)) && InRangeIndex < 63) {
            SubClassOptionalData |= (InRangeIndex + 1) << 1;
        }
        Key = new ConstantExprKeyType(InstructionKind_.GetElementPtr, ArgVec, 0, (cast(ubyte)(SubClassOptionalData)), 返回零值!(uint[])(), 返回零值!(int[])(), Ty);
        return CEGet_.s·getOrCreate(ReqTy, Key);
    }
    static Constant s·get(uint oc, Constant C1, Constant C2, uint Flags = ··null!(uint), 类型_ OnlyIfReducedTy = ··null!(类型_)) {
        Constant FC = CFold_.s·ConstantFoldBinaryInstruction(oc, C1, C2);
        if (FC !is ··null!(Constant)) {
            return FC;
        }
        if (OnlyIfReducedTy == C1.类型) {
            return ··null!(Constant);
        }
        Constant[] ArgVec = [C1, C2];
        ConstantExprKeyType key = new ConstantExprKeyType(.转换枚举!(InstructionKind_)(oc), ArgVec, 0, Flags ? (cast(ubyte)(Flags)) : 0);
        return CEGet_.s·getOrCreate(C1.类型, key);
    }
    static Constant s·get(uint oc, Constant C1, uint Flags = ··null!(uint), bool OnlyIfReduced = false) {
        Constant FC = CFold_.s·ConstantFoldUnaryInstruction(oc, C1);
        if (FC !is ··null!(Constant)) {
            return FC;
        }
        Constant[] ArgVec = [C1];
        ConstantExprKeyType key = new ConstantExprKeyType(.转换枚举!(InstructionKind_)(oc), ArgVec, 0, Flags ? (cast(ubyte)(Flags)) : 0);
        return CEGet_.s·getOrCreate(C1.类型, key);
    }
    static Constant s·getCast(uint oc, Constant C, 类型_ Ty, bool OnlyIfReduced = false) {
        InstructionKind_ opc = .转换枚举!(InstructionKind_)(oc);
        assert(.castIsValid(opc, C.类型, Ty), "Invalid constantexpr cast_!"c);
        switch (opc) {
            case InstructionKind_.Trunc: {
                return CEGet_.s·getTrunc(C, Ty, OnlyIfReduced);
            }
            case InstructionKind_.ZExt: {
                return CEGet_.s·getZExt(C, Ty, OnlyIfReduced);
            }
            case InstructionKind_.SExt: {
                return CEGet_.s·getSExt(C, Ty, OnlyIfReduced);
            }
            case InstructionKind_.FPTrunc: {
                return CEGet_.s·getFPTrunc(C, Ty, OnlyIfReduced);
            }
            case InstructionKind_.FPExt: {
                return CEGet_.s·getFPExtend(C, Ty, OnlyIfReduced);
            }
            case InstructionKind_.UIToFP: {
                return CEGet_.s·getUIToFP(C, Ty, OnlyIfReduced);
            }
            case InstructionKind_.SIToFP: {
                return CEGet_.s·getSIToFP(C, Ty, OnlyIfReduced);
            }
            case InstructionKind_.FPToUI: {
                return CEGet_.s·getFPToUI(C, Ty, OnlyIfReduced);
            }
            case InstructionKind_.FPToSI: {
                return CEGet_.s·getFPToSI(C, Ty, OnlyIfReduced);
            }
            case InstructionKind_.PtrToInt: {
                return CEGet_.s·getPtrToInt(C, Ty, OnlyIfReduced);
            }
            case InstructionKind_.IntToPtr: {
                return CEGet_.s·getIntToPtr(C, Ty, OnlyIfReduced);
            }
            case InstructionKind_.BitCast: {
                return CEGet_.s·getBitCast(C, Ty, OnlyIfReduced);
            }
            case InstructionKind_.AddrSpaceCast: {
                return CEGet_.s·getAddrSpaceCast(C, Ty, OnlyIfReduced);
            }
            default: {
                assert(false, "Invalid cast_ opcode"c);
                break;
            }
        }
        return ··null!(Constant);
    }
    static Constant s·getTrunc(Constant C, 类型_ Ty, bool OnlyIfReduced = false) {
        return CEGet_.s·getFoldedCast(InstructionKind_.Trunc, C, Ty, OnlyIfReduced);
    }
    static Constant s·getSExt(Constant C, 类型_ Ty, bool OnlyIfReduced = false) {
        return CEGet_.s·getFoldedCast(InstructionKind_.SExt, C, Ty, OnlyIfReduced);
    }
    static Constant s·getZExt(Constant C, 类型_ Ty, bool OnlyIfReduced = false) {
        return CEGet_.s·getFoldedCast(InstructionKind_.ZExt, C, Ty, OnlyIfReduced);
    }
    static Constant s·getFPTrunc(Constant C, 类型_ Ty, bool OnlyIfReduced = false) {
        return CEGet_.s·getFoldedCast(InstructionKind_.FPTrunc, C, Ty, OnlyIfReduced);
    }
    static Constant s·getFPExtend(Constant C, 类型_ Ty, bool OnlyIfReduced = false) {
        return CEGet_.s·getFoldedCast(InstructionKind_.FPExt, C, Ty, OnlyIfReduced);
    }
    static Constant s·getUIToFP(Constant C, 类型_ Ty, bool OnlyIfReduced = false) {
        return CEGet_.s·getFoldedCast(InstructionKind_.UIToFP, C, Ty, OnlyIfReduced);
    }
    static Constant s·getSIToFP(Constant C, 类型_ Ty, bool OnlyIfReduced = false) {
        return CEGet_.s·getFoldedCast(InstructionKind_.SIToFP, C, Ty, OnlyIfReduced);
    }
    static Constant s·getFPToUI(Constant C, 类型_ Ty, bool OnlyIfReduced = false) {
        return CEGet_.s·getFoldedCast(InstructionKind_.FPToUI, C, Ty, OnlyIfReduced);
    }
    static Constant s·getFPToSI(Constant C, 类型_ Ty, bool OnlyIfReduced = false) {
        return CEGet_.s·getFoldedCast(InstructionKind_.FPToSI, C, Ty, OnlyIfReduced);
    }
    static Constant s·getPtrToInt(Constant C, 类型_ Ty, bool OnlyIfReduced = false) {
        return CEGet_.s·getFoldedCast(InstructionKind_.PtrToInt, C, Ty, OnlyIfReduced);
    }
    static Constant s·getIntToPtr(Constant C, 类型_ Ty, bool OnlyIfReduced = false) {
        return CEGet_.s·getFoldedCast(InstructionKind_.IntToPtr, C, Ty, OnlyIfReduced);
    }
    static Constant s·getBitCast(Constant C, 类型_ DstTy, bool OnlyIfReduced = false) {
        assert(.castIsValid(InstructionKind_.BitCast, C.类型, DstTy), "Invalid constantexpr bitcast!"c);
        // It is common to ask for a bitcast of a value to its own type, handle this
        // speedily.
        if (C.类型 == DstTy) {
            return C;
        }
        return CEGet_.s·getFoldedCast(InstructionKind_.BitCast, C, DstTy, OnlyIfReduced);
    }
    static Constant s·getAddrSpaceCast(Constant C, 类型_ DstTy, bool OnlyIfReduced = false) {
        assert(.castIsValid(InstructionKind_.AddrSpaceCast, C.类型, DstTy), "Invalid constantexpr bitcast!"c);
        指针类型_ SrcScalarTy = .cast_!(指针类型_)(.getScalarType(C.类型));
        指针类型_ DstScalarTy = .cast_!(指针类型_)(.getScalarType(DstTy));
        if ((SrcScalarTy !is ··null!(指针类型_)) && (DstScalarTy !is ··null!(指针类型_)) && !PTy_.s·hasSameElementTypeAs(SrcScalarTy, DstScalarTy)) {
            类型_ MidTy = .PtrTy_getWithSamePointeeType(DstScalarTy, SrcScalarTy.地址);
            向量类型_ VT = .cast_!(向量类型_)(DstTy);
            if (VT !is ··null!(向量类型_)) {
                MidTy = TGet_.s·VTy_get(MidTy, false, VT.数量);
            }
            C = CEGet_.s·getBitCast(C, MidTy);
        }
        return CEGet_.s·getFoldedCast(InstructionKind_.AddrSpaceCast, C, DstTy, OnlyIfReduced);
    }
    static Constant s·getPointerCast(Constant S, 类型_ Ty) {
        assert(.isPtrOrPtrVectorTy(S.类型), "Invalid cast_"c);
        assert((.isIntOrIntVectorTy(Ty) || .isPtrOrPtrVectorTy(Ty)), "Invalid cast_"c);
        if (.isIntOrIntVectorTy(Ty)) {
            return CEGet_.s·getPtrToInt(S, Ty);
        }
        uint SrcAS = (cast(指针类型_)(S.类型)).地址;
        if (.isPtrOrPtrVectorTy(Ty) && SrcAS != (cast(指针类型_)(Ty)).地址) {
            return CEGet_.s·getAddrSpaceCast(S, Ty);
        }
        return CEGet_.s·getBitCast(S, Ty);
    }
    static Constant s·getSExtOrBitCast(Constant C, 类型_ Ty) {
        if (.getScalarSizeInBits(C.类型) == .getScalarSizeInBits(Ty)) {
            return CEGet_.s·getBitCast(C, Ty);
        }
        return CEGet_.s·getSExt(C, Ty);
    }
    static Constant s·getNeg(Constant C, bool HasNUW, bool HasNSW) {
        assert(.isIntOrIntVectorTy(C.类型), "Cannot NEG a nonintegral value!"c);
        return CEGet_.s·getSub(.ConstantFP_getZeroValueForNegation(C.类型), C, HasNUW, HasNSW);
    }
    static Constant s·getFNeg(Constant C) {
        assert(.isFPOrFPVectorTy(C.类型), "Cannot FNEG a non-floating-point value!"c);
        return CEGet_.s·get(InstructionKind_.FNeg, C);
    }
    static Constant s·getNot(Constant C) {
        assert(.isIntOrIntVectorTy(C.类型), "Cannot NOT a nonintegral value!"c);
        return CEGet_.s·get(InstructionKind_.Xor, C, .getAllOnesValue(C.类型));
    }
    static Constant s·getAdd(Constant C1, Constant C2, bool HasNUW, bool HasNSW) {
        uint Flags = (cast(uint)(HasNUW ? OverflowingBinaryOperator_.NoUnsignedWrap : 0)) | (cast(uint)(HasNSW ? OverflowingBinaryOperator_.NoSignedWrap : 0));
        return CEGet_.s·get(InstructionKind_.Add, C1, C2, Flags);
    }
    static Constant s·getFAdd(Constant C1, Constant C2) {
        return CEGet_.s·get(InstructionKind_.FAdd, C1, C2);
    }
    static Constant s·getSub(Constant C1, Constant C2, bool HasNUW, bool HasNSW) {
        uint Flags = (cast(uint)(HasNUW ? OverflowingBinaryOperator_.NoUnsignedWrap : 0)) | (cast(uint)(HasNSW ? OverflowingBinaryOperator_.NoSignedWrap : 0));
        return CEGet_.s·get(InstructionKind_.Sub, C1, C2, Flags);
    }
    static Constant s·getFSub(Constant C1, Constant C2) {
        return CEGet_.s·get(InstructionKind_.FSub, C1, C2);
    }
    static Constant s·getMul(Constant C1, Constant C2, bool HasNUW, bool HasNSW) {
        uint Flags = (cast(uint)(HasNUW ? OverflowingBinaryOperator_.NoUnsignedWrap : 0)) | (cast(uint)(HasNSW ? OverflowingBinaryOperator_.NoSignedWrap : 0));
        return CEGet_.s·get(InstructionKind_.Mul, C1, C2, Flags);
    }
    static Constant s·getFMul(Constant C1, Constant C2) {
        return CEGet_.s·get(InstructionKind_.FMul, C1, C2);
    }
    static Constant s·getUDiv(Constant C1, Constant C2, bool isExact) {
        return CEGet_.s·get(InstructionKind_.UDiv, C1, C2, (cast(uint)(isExact ? PossiblyExactOperator_.IsExact : 0)));
    }
    static Constant s·getSDiv(Constant C1, Constant C2, bool isExact) {
        return CEGet_.s·get(InstructionKind_.SDiv, C1, C2, (cast(uint)(isExact ? PossiblyExactOperator_.IsExact : 0)));
    }
    static Constant s·getFDiv(Constant C1, Constant C2) {
        return CEGet_.s·get(InstructionKind_.FDiv, C1, C2);
    }
    static Constant s·getURem(Constant C1, Constant C2) {
        return CEGet_.s·get(InstructionKind_.URem, C1, C2);
    }
    static Constant s·getSRem(Constant C1, Constant C2) {
        return CEGet_.s·get(InstructionKind_.SRem, C1, C2);
    }
    static Constant s·getFRem(Constant C1, Constant C2) {
        return CEGet_.s·get(InstructionKind_.FRem, C1, C2);
    }
    static Constant s·getAnd(Constant C1, Constant C2) {
        return CEGet_.s·get(InstructionKind_.And, C1, C2);
    }
    static Constant s·getOr(Constant C1, Constant C2) {
        return CEGet_.s·get(InstructionKind_.Or, C1, C2);
    }
    static Constant s·getXor(Constant C1, Constant C2) {
        return CEGet_.s·get(InstructionKind_.Xor, C1, C2);
    }
    static Constant s·getUMin(Constant C1, Constant C2) {
        Constant Cmp = CEGet_.s·getICmp(CmpInst_Predicate_.ICMP_ULT, C1, C2);
        return CEGet_.s·getSelect(Cmp, C1, C2);
    }
    static Constant s·getShl(Constant C1, Constant C2, bool HasNUW, bool HasNSW) {
        uint Flags = (cast(uint)(HasNUW ? OverflowingBinaryOperator_.NoUnsignedWrap : 0)) | (cast(uint)(HasNSW ? OverflowingBinaryOperator_.NoSignedWrap : 0));
        return CEGet_.s·get(InstructionKind_.Shl, C1, C2, Flags);
    }
    static Constant s·getLShr(Constant C1, Constant C2, bool isExact) {
        return CEGet_.s·get(InstructionKind_.LShr, C1, C2, (cast(uint)(isExact ? PossiblyExactOperator_.IsExact : 0)));
    }
    static Constant s·getAShr(Constant C1, Constant C2, bool isExact) {
        return CEGet_.s·get(InstructionKind_.AShr, C1, C2, (cast(uint)(isExact ? PossiblyExactOperator_.IsExact : 0)));
    }
    static Constant s·getExactLogBase2(Constant C) {
        类型_ Ty = C.类型;
        APInt_ IVal;
        if (.match(C, .m_APInt(&IVal)) && IVal.isPowerOf2()) {
            return CGet_.s·CInt_get(Ty, IVal.logBase2(), false);
        }
        // FIXME: We can extract pow of 2 of splat constant 循环 scalable vectors.
        向量类型_ VecTy = .dyn_cast!(向量类型_)(Ty);
        if (VecTy is ··null!(向量类型_)) {
            return ··null!(Constant);
        }
        Constant[] Elts = 创建数组!(Constant)();
        {
            for (uint I = 0; I < VecTy.数量; ++I) {
                Constant Elt = .getAggregateElement(C, I);
                if (Elt is ··null!(Constant)) {
                    return // Note that log2(iN undef) is NOT iN undef, because log2(iN undef) u< N.
                     ··null!(Constant);
                }
                // Note that log2(iN undef) is NOT iN undef, because log2(iN undef) u< N.
                if (.isUndefValue(Elt)) {
                    .追加!(Constant)(Elts, CGet_.s·getNullValue(.getScalarType(Ty)));
                    continue;
                }
                if (!.match(Elt, .m_APInt(&IVal)) || !IVal.isPowerOf2()) {
                    return ··null!(Constant);
                }
                .追加!(Constant)(Elts, CGet_.s·CInt_get(.getScalarType(Ty), IVal.logBase2(), false));
            }
        }
        return CGet_.s·Vector_get(Elts);
    }
    static Constant s·getSelect(Constant C, Constant V1, Constant V2, 类型_ OnlyIfReducedTy = ··null!(类型_)) {
        assert(.SelectInst_areInvalidOperands(C, V1, V2) is ··null!(dstring), "Invalid select operands"c);
        Constant SC = CFold_.s·ConstantFoldSelectInstruction(C, V1, V2);
        if (SC !is ··null!(Constant)) {
            return SC;
        } // Fold common cases
        if (OnlyIfReducedTy == V1.类型) {
            return ··null!(Constant);
        }
        Constant[] ArgVec = [C, V1, V2];
        ConstantExprKeyType Key = new ConstantExprKeyType(InstructionKind_.Select, ArgVec);
        return CEGet_.s·getOrCreate(V1.类型, Key);
    }
    static Constant s·getCompare(uint Predicate, Constant C1, Constant C2, bool OnlyIfReduced) {
        assert(C1.类型 == C2.类型, "Op types should be identical!"c);
        switch (Predicate) {
            case CmpInst_Predicate_.FCMP_FALSE:
            case CmpInst_Predicate_.FCMP_OEQ:
            case CmpInst_Predicate_.FCMP_OGT:
            case CmpInst_Predicate_.FCMP_OGE:
            case CmpInst_Predicate_.FCMP_OLT:
            case CmpInst_Predicate_.FCMP_OLE:
            case CmpInst_Predicate_.FCMP_ONE:
            case CmpInst_Predicate_.FCMP_ORD:
            case CmpInst_Predicate_.FCMP_UNO:
            case CmpInst_Predicate_.FCMP_UEQ:
            case CmpInst_Predicate_.FCMP_UGT:
            case CmpInst_Predicate_.FCMP_UGE:
            case CmpInst_Predicate_.FCMP_ULT:
            case CmpInst_Predicate_.FCMP_ULE:
            case CmpInst_Predicate_.FCMP_UNE:
            case CmpInst_Predicate_.FCMP_TRUE: {
                return CEGet_.s·getFCmp(Predicate, C1, C2, OnlyIfReduced);
            }
            case CmpInst_Predicate_.ICMP_EQ:
            case CmpInst_Predicate_.ICMP_NE:
            case CmpInst_Predicate_.ICMP_UGT:
            case CmpInst_Predicate_.ICMP_UGE:
            case CmpInst_Predicate_.ICMP_ULT:
            case CmpInst_Predicate_.ICMP_ULE:
            case CmpInst_Predicate_.ICMP_SGT:
            case CmpInst_Predicate_.ICMP_SGE:
            case CmpInst_Predicate_.ICMP_SLT:
            case CmpInst_Predicate_.ICMP_SLE: {
                return CEGet_.s·getICmp(Predicate, C1, C2, OnlyIfReduced);
            }
            default: {
                assert(false, "Invalid CmpInst predicate"c);
                return ··null!(Constant);
            }
        }
    }
    static Constant s·getICmp(uint pred, Constant LHS, Constant RHS, bool OnlyIfReduced = false) {
        assert(LHS.类型 == RHS.类型, "xx"c);
        assert(CmpInst_.s·isIntPredicate(.转换枚举!(CmpInst_Predicate_)(pred)), "Invalid ICmp Predicate"c);
        Constant FC = CFold_.s·ConstantFoldCompareInstruction(pred, LHS, RHS);
        if (FC !is ··null!(Constant)) {
            return FC;
        } // Fold a few common cases...
        if (OnlyIfReduced) {
            return ··null!(Constant);
        }
        // Look up the constant in the table first to ensure uniqueness
        Constant[] ArgVec = [LHS, RHS];
        // Get the key type with both the opcode and predicate
        ConstantExprKeyType Key = new ConstantExprKeyType(InstructionKind_.ICmp, ArgVec, (cast(ushort)(pred)));
        类型_ ResultTy = TGet_.s·IntTy_get(1);
        向量类型_ VT = .dyn_cast!(向量类型_)(LHS.类型);
        if (VT !is ··null!(向量类型_)) {
            ResultTy = TGet_.s·VTy_get(ResultTy, VTy_.s·getElementCount(VT));
        }
        return CEGet_.s·getOrCreate(ResultTy, Key);
    }
    static Constant s·getFCmp(uint pred, Constant LHS, Constant RHS, bool OnlyIfReduced = false) {
        assert(LHS.类型 == RHS.类型, "xx"c);
        assert(CmpInst_.s·isFPPredicate(.转换枚举!(CmpInst_Predicate_)(pred)), "Invalid FCmp Predicate"c);
        Constant FC = CFold_.s·ConstantFoldCompareInstruction(pred, LHS, RHS);
        if (FC !is ··null!(Constant)) {
            return FC;
        } // Fold a few common cases...
        if (OnlyIfReduced) {
            return ··null!(Constant);
        }
        // Look up the constant in the table first to ensure uniqueness
        Constant[] ArgVec = [LHS, RHS];
        // Get the key type with both the opcode and predicate
        ConstantExprKeyType Key = new ConstantExprKeyType(InstructionKind_.FCmp, ArgVec, (cast(ushort)(pred)));
        类型_ ResultTy = TGet_.s·IntTy_get(1);
        向量类型_ VT = .dyn_cast!(向量类型_)(LHS.类型);
        if (VT !is ··null!(向量类型_)) {
            ResultTy = TGet_.s·VTy_get(ResultTy, VTy_.s·getElementCount(VT));
        }
        return CEGet_.s·getOrCreate(ResultTy, Key);
    }
    static Constant s·getInsertElement(Constant Val, Constant Elt, Constant Idx, 类型_ OnlyIfReducedTy = ··null!(类型_)) {
        assert(.isVectorType(Val.类型), "Tried to create insertelement operation on non-vector type!"c);
        assert(Elt.类型 == .cast_!(向量类型_)(Val.类型).元素类型, "Insertelement types must match!"c);
        assert(.isIntegerTy(Idx.类型), "Insertelement index must be i32 type!"c);
        Constant FC = CFold_.s·ConstantFoldInsertElementInstruction(Val, Elt, Idx);
        if (FC !is ··null!(Constant)) {
            return FC;
        } // Fold a few common cases.
        if (OnlyIfReducedTy == Val.类型) {
            return ··null!(Constant);
        }
        // Look up the constant in the table first to ensure uniqueness
        Constant[] ArgVec = [Val, Elt, Idx];
        ConstantExprKeyType Key = new ConstantExprKeyType(InstructionKind_.InsertElement, ArgVec);
        return CEGet_.s·getOrCreate(Val.类型, Key);
    }
    static Constant s·getShuffleVector(Constant V1, Constant V2, int[] Mask, 类型_ OnlyIfReducedTy = ··null!(类型_)) {
        assert(SVI_.s·isValidOperands(V1, V2, Mask), "Invalid shuffle vector constant expr operands!"c);
        Constant FC = CFold_.s·ConstantFoldShuffleVectorInstruction(V1, V2, Mask);
        if (FC !is ··null!(Constant)) {
            return FC;
        } // Fold a few common cases.
        uint NElts = (cast(uint)(Mask.length));
        向量类型_ V1VTy = .cast_!(向量类型_)(V1.类型);
        类型_ EltTy = V1VTy.元素类型;
        bool TypeIsScalable = .isScalableVectorType(V1VTy);
        向量类型_ ShufTy = TGet_.s·VTy_get(EltTy, TypeIsScalable, NElts);
        if (OnlyIfReducedTy == ShufTy) {
            return ··null!(Constant);
        }
        // Look up the constant in the table first to ensure uniqueness
        Constant[] ArgVec = [V1, V2];
        ConstantExprKeyType Key = new ConstantExprKeyType(InstructionKind_.ShuffleVector, ArgVec, 0, 0, 返回零值!(uint[])(), Mask);
        return CEGet_.s·getOrCreate(ShufTy, Key);
    }
    static Constant s·getInsertValue(Constant Agg, Constant Val, uint[] Idxs, 类型_ OnlyIfReducedTy = ··null!(类型_)) {
        assert(.isFirstClassType(Agg.类型), "Non-first-class type for constant insertvalue expression"c);
        assert(GEV_.s·getIndexedType(Agg.类型, Idxs) == Val.类型, "insertvalue indices invalid!"c);
        类型_ ReqTy = Val.类型;
        Constant FC = CFold_.s·ConstantFoldInsertValueInstruction(Agg, Val, Idxs);
        if (FC !is ··null!(Constant)) {
            return FC;
        }
        if (OnlyIfReducedTy == ReqTy) {
            return ··null!(Constant);
        }
        Constant[] ArgVec = [Agg, Val];
        ConstantExprKeyType Key = new ConstantExprKeyType(InstructionKind_.InsertValue, ArgVec, 0, 0, Idxs);
        return CEGet_.s·getOrCreate(ReqTy, Key);
    }
    static Constant s·getExtractValue(Constant Agg, uint[] Idxs, 类型_ OnlyIfReducedTy = ··null!(类型_)) {
        assert(.isFirstClassType(Agg.类型), "Tried to create extractelement operation on non-first-class type!"c);
        类型_ ReqTy = GEV_.s·getIndexedType(Agg.类型, Idxs);
        assert(ReqTy !is ··null!(类型_), "extractvalue indices invalid!"c);
        assert(.isFirstClassType(Agg.类型), "Non-first-class type for constant extractvalue expression"c);
        Constant FC = CFold_.s·ConstantFoldExtractValueInstruction(Agg, Idxs);
        if (FC !is ··null!(Constant)) {
            return FC;
        }
        if (OnlyIfReducedTy == ReqTy) {
            return ··null!(Constant);
        }
        Constant[] ArgVec = [Agg];
        ConstantExprKeyType Key = new ConstantExprKeyType(InstructionKind_.ExtractValue, ArgVec, 0, 0, Idxs);
        return CEGet_.s·getOrCreate(ReqTy, Key);
    }
    static Constant s·getWithOperands(ConstantExpr that, Constant[] Ops, 类型_ Ty, bool OnlyIfReduced, 类型_ SrcTy) {
        assert(Ops.length == that.Ops.length, "Operand count mismatch!"c);
        // If no operands changed 返回 self.
        if (Ty == that.类型 && rangeEquals!(Value)(cast(Value[])(Ops), that.Ops, 0, 0)) {
            return .cast_!(ConstantExpr)(that);
        }
        类型_ OnlyIfReducedTy = OnlyIfReduced ? Ty : 返回零值!(类型_)();
        switch (that.Opc) {
            case InstructionKind_.Trunc:
            case InstructionKind_.ZExt:
            case InstructionKind_.SExt:
            case InstructionKind_.FPTrunc:
            case InstructionKind_.FPExt:
            case InstructionKind_.UIToFP:
            case InstructionKind_.SIToFP:
            case InstructionKind_.FPToUI:
            case InstructionKind_.FPToSI:
            case InstructionKind_.PtrToInt:
            case InstructionKind_.IntToPtr:
            case InstructionKind_.BitCast:
            case InstructionKind_.AddrSpaceCast: {
                return CEGet_.s·getCast(that.Opc, Ops[0], Ty, OnlyIfReduced);
            }
            case InstructionKind_.Select: {
                return CEGet_.s·getSelect(Ops[0], Ops[1], Ops[2], OnlyIfReducedTy);
            }
            case InstructionKind_.InsertElement: {
                return CEGet_.s·getInsertElement(Ops[0], Ops[1], Ops[2], OnlyIfReducedTy);
            }
            case InstructionKind_.ExtractElement: {
                return CEGet_.s·getExtractElement(Ops[0], Ops[1], OnlyIfReducedTy);
            }
            case InstructionKind_.InsertValue: {
                return CEGet_.s·getInsertValue(Ops[0], Ops[1], CExp_.s·getIndices(that), OnlyIfReducedTy);
            }
            case InstructionKind_.ExtractValue: {
                return CEGet_.s·getExtractValue(Ops[0], CExp_.s·getIndices(that), OnlyIfReducedTy);
            }
            case InstructionKind_.FNeg: {
                return CEGet_.s·getFNeg(Ops[0]);
            }
            case InstructionKind_.ShuffleVector: {
                return CEGet_.s·getShuffleVector(Ops[0], Ops[1], CExp_.s·getShuffleMask(that), OnlyIfReducedTy);
            }
            case InstructionKind_.GetElementPtr: {
                GetElementPtrConstantExpr GEPO = .cast_!(GetElementPtrConstantExpr)(that);
                return CEGet_.s·getGetElementPtr(SrcTy ? SrcTy : GEPO.SrcElementTy, Ops[0], cast(Value[])(Ops[1 .. $]), (GEPO.SubclassOptionalData & 1) != 0, GEP_.s·getInRangeIndex(GEPO), OnlyIfReducedTy);
            }
            case InstructionKind_.ICmp:
            case InstructionKind_.FCmp: {
                return CEGet_.s·getCompare(CExp_.s·getPredicate(that), Ops[0], Ops[1], (OnlyIfReducedTy !is ··null!(类型_)));
            }
            default: {
                return CEGet_.s·get(that.Opc, Ops[0], Ops[1], (cast(uint)(that.SubclassOptionalData)), OnlyIfReducedTy);
            }
        }
    }
}
class CGet_ {
    this() { }
    static ConstantInt s·CInt_get(APInt_ V) {
        整数类型_ Ty = TGet_.s·IntTy_get(V.getBitWidth());
        dstring id = .获取类型文本Id(Ty) ~ ":I:"d ~ V.toStringUnsigned(10);
        if (IntConstants.具有(id)) {
            return IntConstants.获取(id);
        }
        ConstantInt IntC = new ConstantInt(Ty, V);
        IntConstants.p·设置(id, IntC);
        return IntConstants.获取(id);
    }
    static Constant s·CInt_get(类型_ Ty, APInt_ V) {
        ConstantInt C = CGet_.s·CInt_get(V);
        assert(C.类型 == .getScalarType(Ty), "err"c);
        if (.isVectorType(Ty)) {
            return CGet_.s·Vector_getSplat(VTy_.s·getElementCount((cast(向量类型_)(Ty))), C);
        }
        return C;
    }
    static Constant s·CInt_get(类型_ Ty, ulong V, bool isSig) {
        整数类型_ NTy = (cast(整数类型_)(.getScalarType(Ty)));
        Constant C = CGet_.s·CInt_get(NTy, V, isSig);
        if (.isVectorType(Ty)) {
            return CGet_.s·Vector_getSplat(VTy_.s·getElementCount((cast(向量类型_)(Ty))), C);
        }
        return C;
    }
    static Constant s·CInt_get(类型_ Ty, bool V) {
        整数类型_ NTy = (cast(整数类型_)(.getScalarType(Ty)));
        Constant C = CGet_.s·CInt_get(NTy, V ? 1 : 0, false);
        if (.isVectorType(Ty)) {
            return CGet_.s·Vector_getSplat(VTy_.s·getElementCount((cast(向量类型_)(Ty))), C);
        }
        return C;
    }
    static Constant s·CInt_get(整数类型_ Ty, ulong V, bool isSig) {
        APInt_ N = new APInt_(Ty.位数, V, isSig);
        return CGet_.s·CInt_get(N);
    }
    static Constant s·CInt_getSigned(整数类型_ Ty, long V) {
        return CGet_.s·CInt_get(Ty, V, true);
    }
    static Constant s·CInt_getSigned(类型_ Ty, long V) {
        return CGet_.s·CInt_get(Ty, V, true);
    }
    static Constant s·CInt_getTrue() {
        return CGet_.s·CInt_get(.Int1Ty, 1, false);
    }
    static Constant s·CInt_getTrue(类型_ Ty) {
        Constant C = CGet_.s·CInt_getTrue();
        if (.isVectorType(Ty)) {
            return CGet_.s·Vector_getSplat(VTy_.s·getElementCount((cast(向量类型_)(Ty))), C);
        }
        return C;
    }
    static Constant s·CInt_getFalse() {
        return CGet_.s·CInt_get(.Int1Ty, 0, false);
    }
    static Constant s·CInt_getFalse(类型_ Ty) {
        Constant C = CGet_.s·CInt_getFalse();
        if (.isVectorType(Ty)) {
            return CGet_.s·Vector_getSplat(VTy_.s·getElementCount((cast(向量类型_)(Ty))), C);
        }
        return C;
    }
    static Constant s·CInt_getBool(bool V) {
        return V ? CGet_.s·CInt_getTrue() : CGet_.s·CInt_getFalse();
    }
    static Constant s·CInt_getBool(类型_ Ty, bool V) {
        return V ? CGet_.s·CInt_getTrue(Ty) : CGet_.s·CInt_getFalse(Ty);
    }
    static ConstantFP s·CFP_get(APFloat_ V) {
        类型_ Ty = .getFloatingPointTy(V.getSemantics());
        dstring id = .获取类型文本Id(Ty) ~ ":F:"d ~ V.bitcastToAPInt().toStringUnsigned(10);
        if (FPConstants.具有(id)) {
            return FPConstants.获取(id);
        }
        ConstantFP FC = new ConstantFP(Ty, V);
        FPConstants.p·设置(id, FC);
        return FPConstants.获取(id);
    }
    static Constant s·CFP_get(类型_ Ty, double V) {
        APFloat_ F = new APFloat_(V);
        bool ignored = false;
        F.convert(.getFltSemantics(.getScalarType(Ty)), rmNearestTiesToEven, ignored);
        ConstantFP C = CGet_.s·CFP_get(F);
        if (.isVectorType(Ty)) {
            return CGet_.s·Vector_getSplat(VTy_.s·getElementCount((cast(向量类型_)(Ty))), C);
        }
        return C;
    }
    static Constant s·CFP_get(类型_ Ty, APFloat_ F) {
        ConstantFP C = CGet_.s·CFP_get(F);
        if (.isVectorType(Ty)) {
            return CGet_.s·Vector_getSplat(VTy_.s·getElementCount((cast(向量类型_)(Ty))), C);
        }
        return C;
    }
    static Constant s·CFP_get(类型_ Ty, dstring Str) {
        APFloat_ F = new APFloat_(.getFltSemantics(.getScalarType(Ty)), Str);
        ConstantFP C = CGet_.s·CFP_get(F);
        if (.isVectorType(Ty)) {
            return CGet_.s·Vector_getSplat(VTy_.s·getElementCount((cast(向量类型_)(Ty))), C);
        }
        return C;
    }
    static Constant s·CFP_getNaN(类型_ Ty, bool Negative, ulong Payload) {
        FltSemantics_ Semantics = .getFltSemantics(.getScalarType(Ty));
        APFloat_ NaN_ = APFloat_getNaN(Semantics, Negative, Payload);
        ConstantFP C = CGet_.s·CFP_get(NaN_);
        if (.isVectorType(Ty)) {
            return CGet_.s·Vector_getSplat(VTy_.s·getElementCount((cast(向量类型_)(Ty))), C);
        }
        return C;
    }
    static Constant s·CFP_getQNaN(类型_ Ty, bool Negative, APInt_ Payload) {
        FltSemantics_ Semantics = .getFltSemantics(.getScalarType(Ty));
        APFloat_ NaN_ = APFloat_getQNaN(Semantics, Negative, Payload);
        ConstantFP C = CGet_.s·CFP_get(NaN_);
        if (.isVectorType(Ty)) {
            return CGet_.s·Vector_getSplat(VTy_.s·getElementCount((cast(向量类型_)(Ty))), C);
        }
        return C;
    }
    static Constant s·CFP_getSNaN(类型_ Ty, bool Negative, APInt_ Payload) {
        FltSemantics_ Semantics = .getFltSemantics(.getScalarType(Ty));
        APFloat_ NaN_ = APFloat_getSNaN(Semantics, Negative, Payload);
        ConstantFP C = CGet_.s·CFP_get(NaN_);
        if (.isVectorType(Ty)) {
            return CGet_.s·Vector_getSplat(VTy_.s·getElementCount((cast(向量类型_)(Ty))), C);
        }
        return C;
    }
    static Constant s·CFP_getNegativeZero(类型_ Ty) {
        FltSemantics_ Semantics = .getFltSemantics(.getScalarType(Ty));
        APFloat_ NegZero = APFloat_getZero(Semantics, true);
        ConstantFP C = CGet_.s·CFP_get(NegZero);
        if (.isVectorType(Ty)) {
            return CGet_.s·Vector_getSplat(VTy_.s·getElementCount((cast(向量类型_)(Ty))), C);
        }
        return C;
    }
    static Constant s·CFP_getZeroValueForNegation(类型_ Ty) {
        if (.isFPOrFPVectorTy(Ty)) {
            return CGet_.s·CFP_getNegativeZero(Ty);
        }
        return CGet_.s·getNullValue(Ty);
    }
    static Constant s·CFP_getInfinity(类型_ Ty, bool Negative) {
        FltSemantics_ Semantics = .getFltSemantics(.getScalarType(Ty));
        APFloat_ inf_ = APFloat_getInf(Semantics, Negative);
        ConstantFP C = CGet_.s·CFP_get(inf_);
        if (.isVectorType(Ty)) {
            return CGet_.s·Vector_getSplat(VTy_.s·getElementCount((cast(向量类型_)(Ty))), C);
        }
        return C;
    }
    static ConstantPointerNull s·PointerNull_get(指针类型_ Ty) {
        dstring id = .获取类型文本Id(Ty);
        if (CPNConstants.具有(id)) {
            return CPNConstants.获取(id);
        }
        ConstantPointerNull cn = new ConstantPointerNull(Ty);
        CPNConstants.p·设置(id, cn);
        return CPNConstants.获取(id);
    }
    static ConstantAggregateZero s·AggregateZero_get(类型_ Ty) {
        dstring id = .获取类型文本Id(Ty);
        if (CAZConstants.具有(id)) {
            return CAZConstants.获取(id);
        }
        ConstantAggregateZero cn = new ConstantAggregateZero(Ty);
        CAZConstants.p·设置(id, cn);
        return CAZConstants.获取(id);
    }
    static ConstantTokenNone s·TokenNone_get(类型_ Ty) {
        dstring id = .获取类型文本Id(Ty);
        if (TheNoneToken.具有(id)) {
            return TheNoneToken.获取(id);
        }
        ConstantTokenNone cn = new ConstantTokenNone(Ty);
        TheNoneToken.p·设置(id, cn);
        return TheNoneToken.获取(id);
    }
    static PoisonValue s·PoisonValue_get(类型_ Ty) {
        dstring id = .获取类型文本Id(Ty);
        if (PVConstants.具有(id)) {
            return PVConstants.获取(id);
        }
        PoisonValue cn = new PoisonValue(Ty);
        PVConstants.p·设置(id, cn);
        return PVConstants.获取(id);
    }
    static UndefValue s·UndefValue_get(类型_ Ty) {
        dstring id = .获取类型文本Id(Ty);
        if (UVConstants.具有(id)) {
            return UVConstants.获取(id);
        }
        UndefValue cn = new UndefValue(Ty);
        UVConstants.p·设置(id, cn);
        return UVConstants.获取(id);
    }
    static Constant s·getNullValue(类型_ Ty) {
        switch (Ty.种类) {
            case TypeID_.IntegerTyID: {
                return CGet_.s·CInt_get(Ty, 0, false);
            }
            case TypeID_.HalfTyID: {
                return CGet_.s·CFP_get(APFloat_getZero(IEEEhalf()));
            }
            case TypeID_.BFloatTyID: {
                return CGet_.s·CFP_get(APFloat_getZero(BFloat()));
            }
            case TypeID_.FloatTyID: {
                return CGet_.s·CFP_get(APFloat_getZero(IEEEsingle()));
            }
            case TypeID_.DoubleTyID: {
                return CGet_.s·CFP_get(APFloat_getZero(IEEEdouble()));
            }
            case TypeID_.X86_FP80TyID: {
                return CGet_.s·CFP_get(APFloat_getZero(x87DoubleExtended()));
            }
            case TypeID_.FP128TyID: {
                return CGet_.s·CFP_get(APFloat_getZero(IEEEquad()));
            }
            case TypeID_.PPC_FP128TyID: {
                return CGet_.s·CFP_get(new APFloat_(PPCDoubleDouble(), APInt_getZero(128)));
            }
            case TypeID_.PointerTyID: {
                return CGet_.s·PointerNull_get((cast(指针类型_)(Ty)));
            }
            case TypeID_.StructTyID:
            case TypeID_.ArrayTyID:
            case TypeID_.FixedVectorTyID:
            case TypeID_.ScalableVectorTyID: {
                return CGet_.s·AggregateZero_get(Ty);
            }
            case TypeID_.TokenTyID: {
                return CGet_.s·TokenNone_get(Ty);
            }
            default: break;
        }
        assert(false, "不可及"c);
        return 返回零值!(Constant)();
    }
    static Constant s·DataSequential_getImpl(类型_ Ty, char[] Data) {
        if ((Data is ··null!(char[])) || Data.length == 0 || .全是零值(Data)) {
            return CGet_.s·AggregateZero_get(Ty);
        }
        dstring id = .获取类型文本Id(Ty) ~ " :I: "d ~ ·to!(dstring)(·to!(string)(Data));
        if (CDSConstants.具有(id)) {
            return CDSConstants.获取(id);
        }
        if (Ty.种类 == TypeID_.ArrayTyID) {
            ConstantDataArray Val = new ConstantDataArray(Ty, Data);
            CDSConstants.p·设置(id, Val);
        }
        else {
            ConstantDataVector Val = new ConstantDataVector(Ty, Data);
            CDSConstants.p·设置(id, Val);
        }
        return CDSConstants.获取(id);
    }
    static Constant s·Array_get(数组类型_ Ty, Constant[] V) {
        Constant C = CGet_.s·Array_getImpl(Ty, V);
        if (C !is ··null!(Constant)) {
            return C;
        }
        dstring 键 = .获取类型文本Id(Ty) ~ " :V: "d ~ .获取值列表文本Id(cast(Value[])(V));
        if (ArrayConstants.具有(键)) {
            return ArrayConstants.获取(键);
        }
        ConstantArray VV = new ConstantArray(Ty, V);
        ArrayConstants.p·设置(键, VV);
        return ArrayConstants.获取(键);
    }
    static Constant s·Array_getImpl(数组类型_ Ty, Constant[] V) {
        if ((V is ··null!(Constant[])) || V.length == 0) {
            return CGet_.s·AggregateZero_get(Ty);
        }
        foreach (Constant v; V) {
            assert(v.类型 == Ty, "输出成员类型不同"c);
        }
        Constant C = V[0];
        if (C.种类 == ValueTy_.PoisonValueVal && .rangeOnlyContains(V, C)) {
            return CGet_.s·PoisonValue_get(Ty);
        }
        if (C.种类 == ValueTy_.UndefValueVal && .rangeOnlyContains(V, C)) {
            return CGet_.s·UndefValue_get(Ty);
        }
        if (.isNullValue(C) && .rangeOnlyContains(V, C)) {
            return CGet_.s·AggregateZero_get(Ty);
        }
        if (.isElementTypeCompatible(C.类型)) {
            return .getSequenceIfElementsMatch(V, (类型_ _, char[] es) {
                return CGet_.s·DataSequential_getImpl(Ty, es);
            });
        }
        return ··null!(Constant);
    }
    static Constant s·Vector_get(Constant[] V) {
        Constant C = CGet_.s·Vector_getImpl(V);
        if (C !is ··null!(Constant)) {
            return C;
        }
        Constant V_0 = V[0];
        向量类型_ T = TGet_.s·VTy_get(V_0.类型, false, (cast(uint)(V.length)));
        dstring 键 = .获取类型文本Id(T) ~ " :V: "d ~ .获取值列表文本Id(cast(Value[])(V));
        if (VectorConstants.具有(键)) {
            return VectorConstants.获取(键);
        }
        ConstantVector VV = new ConstantVector(T, V);
        VectorConstants.p·设置(键, VV);
        return VectorConstants.获取(键);
    }
    static Constant s·DataVector_getSplat(uint NumElts, Constant V) {
        assert(.isElementTypeCompatible(V.类型), "Element type not compatible with ConstantData"c);
        if (V.种类 == ValueTy_.ConstantIntVal) {
            ConstantInt CI = (cast(ConstantInt)(V));
            if (CI.类型 == .Int8Ty) {
                ubyte[] Elts = .crateSmallVector!(ubyte)(NumElts, (cast(ubyte)(CI.Val.getZExtValue())));
                return CGet_.s·DataSequential_getImpl(TGet_.s·VTy_get(.Int8Ty, false, (cast(uint)(Elts.length))), .转换为字符8数组!(ubyte)(Elts));
            }
            if (CI.类型 == .Int16Ty) {
                ushort[] Elts = .crateSmallVector!(ushort)(NumElts, (cast(ushort)(CI.Val.getZExtValue())));
                return CGet_.s·DataSequential_getImpl(TGet_.s·VTy_get(.Int16Ty, false, (cast(uint)(Elts.length * 2))), .转换为字符8数组!(ushort)(Elts));
            }
            if (CI.类型 == .Int32Ty) {
                uint[] Elts = .crateSmallVector!(uint)(NumElts, (cast(uint)(CI.Val.getZExtValue())));
                return CGet_.s·DataSequential_getImpl(TGet_.s·VTy_get(.Int32Ty, false, (cast(uint)(Elts.length * 4))), .转换为字符8数组!(uint)(Elts));
            }
            assert(CI.类型 == .Int64Ty, "Unsupported ConstantData type"c);
            ulong[] Elts = .crateSmallVector!(ulong)(NumElts, CI.Val.getZExtValue());
            return CGet_.s·DataSequential_getImpl(TGet_.s·VTy_get(.Int64Ty, false, (cast(uint)(Elts.length * 8))), .转换为字符8数组!(ulong)(Elts));
        }
        if (V.种类 == ValueTy_.ConstantFPVal) {
            ConstantFP CFP = (cast(ConstantFP)(V));
            if (CFP.类型 == .HalfTy) {
                ushort[] Elts = .crateSmallVector!(ushort)(NumElts, (cast(ushort)(CFP.Val.bitcastToAPInt().getLimitedValue())));
                return CGet_.s·DataSequential_getImpl(TGet_.s·VTy_get(V.类型, false, (cast(uint)(Elts.length * 2))), .转换为字符8数组!(ushort)(Elts));
            }
            if (CFP.类型 == .BFloatTy) {
                ushort[] Elts = .crateSmallVector!(ushort)(NumElts, (cast(ushort)(CFP.Val.bitcastToAPInt().getLimitedValue())));
                return CGet_.s·DataSequential_getImpl(TGet_.s·VTy_get(V.类型, false, (cast(uint)(Elts.length * 2))), .转换为字符8数组!(ushort)(Elts));
            }
            if (CFP.类型 == .FloatTy) {
                uint[] Elts = .crateSmallVector!(uint)(NumElts, (cast(uint)(CFP.Val.bitcastToAPInt().getLimitedValue())));
                return CGet_.s·DataSequential_getImpl(TGet_.s·VTy_get(V.类型, false, (cast(uint)(Elts.length * 4))), .转换为字符8数组!(uint)(Elts));
            }
            if (CFP.类型 == .DoubleTy) {
                ulong[] Elts = .crateSmallVector!(ulong)(NumElts, CFP.Val.bitcastToAPInt().getLimitedValue());
                return CGet_.s·DataSequential_getImpl(TGet_.s·VTy_get(V.类型, false, (cast(uint)(Elts.length * 8))), .转换为字符8数组!(ulong)(Elts));
            }
        }
        return CGet_.s·Vector_getSplat(ECFixed(NumElts), V);
    }
    static Constant s·Vector_getImpl(Constant[] V) {
        assert((V is ··null!(Constant[])) || V.length == 0, "Vectors can't be empty"c);
        Constant C = V[0];
        向量类型_ T = TGet_.s·VTy_get(C.类型, false, (cast(uint)(V.length)));
        bool isZero = .isNullValue(C);
        bool isUndef = C.种类 == ValueTy_.UndefValueVal;
        bool isPoison = C.种类 == ValueTy_.PoisonValueVal;
        {
            for (int i = 1; i < V.length; ++i) {
                if (V[i] != C) {
                    isZero = isUndef = isPoison = false;
                }
            }
        }
        if (isZero) {
            return CGet_.s·AggregateZero_get(T);
        }
        if (isPoison) {
            return CGet_.s·PoisonValue_get(T);
        }
        if (isUndef) {
            return CGet_.s·UndefValue_get(T);
        }
        if (.isElementTypeCompatible(C.类型)) {
            return .getSequenceIfElementsMatch(V, (类型_ _, char[] es) {
                return CGet_.s·DataSequential_getImpl(T, es);
            });
        }
        return ··null!(Constant);
    }
    static Constant s·Vector_getSplat(ElementCount EC, Constant V) {
        if (!EC.isScalable()) {
            // If this splat is compatible with ConstantDataVector, use it instead of
            // ConstantVector.
            if ((V.种类 == ValueTy_.ConstantFPVal || V.种类 == ValueTy_.ConstantIntVal) && .isElementTypeCompatible(V.类型)) {
                return CGet_.s·DataVector_getSplat(EC.getKnownMinValue(), V);
            }
            Constant[] Elts = .crateSmallVector!(Constant)(EC.getKnownMinValue(), V);
            return CGet_.s·Vector_get(Elts);
        }
        向量类型_ VTy = TGet_.s·VTy_get(V.类型, EC.isScalar(), EC.getKnownMinValue());
        if (.isNullValue(V)) {
            return CGet_.s·AggregateZero_get(VTy);
        }
        else if (V.种类 == ValueTy_.UndefValueVal) {
            return CGet_.s·UndefValue_get(VTy);
        }
        // Move scalar into vector.
        UndefValue UndefV = CGet_.s·UndefValue_get(VTy);
        V = CEGet_.s·getInsertElement(UndefV, V, CGet_.s·CInt_get(.Int32Ty, 0, false));
        // Build shuffle mask to perform the splat.
        int[] Zeros = .crateSmallVector!(int)(EC.getKnownMinValue(), 0);
        // Splat.
        return CEGet_.s·getShuffleVector(V, UndefV, Zeros);
    }
    static Constant s·Struct_get(结构类型_ ST, Constant[] ES) {
        assert(ST.是不透明的 || ST.ContainedTys.length == ES.length, "Incorrect # elements specified to Struct_get"c);
        bool isZero = true;
        bool isUndef = false;
        bool isPoison = false;
        if ((ES !is ··null!(Constant[])) && ES.length != 0) {
            isUndef = ES[0].种类 == ValueTy_.UndefValueVal;
            isPoison = ES[0].种类 == ValueTy_.PoisonValueVal;
            isZero = .isNullValue(ES[0]);
            if (isUndef || isZero) {
                {
                    for (int i = 0; i < ES.length; ++i) {
                        if (!.isNullValue(ES[i])) {
                            isZero = false;
                        }
                        if (ES[i].种类 != ValueTy_.PoisonValueVal) {
                            isPoison = false;
                        }
                        if (ES[i].种类 == ValueTy_.PoisonValueVal || ES[i].种类 != ValueTy_.UndefValueVal) {
                            isUndef = false;
                        }
                    }
                }
            }
        }
        if (isZero) {
            return CGet_.s·AggregateZero_get(ST);
        }
        if (isPoison) {
            return CGet_.s·PoisonValue_get(ST);
        }
        if (isUndef) {
            return CGet_.s·UndefValue_get(ST);
        }
        dstring 键 = .获取类型文本Id(ST) ~ " :SV: "d ~ .获取值列表文本Id(cast(Value[])(ES));
        if (StructConstants.具有(键)) {
            return StructConstants.获取(键);
        }
        ConstantStruct SV = new ConstantStruct(ST, ES);
        StructConstants.p·设置(键, SV);
        return StructConstants.获取(键);
    }
    static BlockAddress s·BlockAddress_get(Function FN, BasicBlock BB) {
        指针类型_ T = TGet_.s·PtrTy_get(.Int8Ty);
        dstring 键 = .获取类型文本Id(T) ~ ":F:"d ~ .获取值文本Id(FN) ~ ":BB:"d ~ .获取值文本Id(BB);
        if (BlockAddresses.具有(键)) {
            return BlockAddresses.获取(键);
        }
        BlockAddress V = new BlockAddress(T, FN, BB);
        BlockAddresses.p·设置(键, V);
        return BlockAddresses.获取(键);
    }
    static DSOLocalEquivalent s·DSOLocalEquivalent_get(GlobalValue GV) {
        dstring 键 = .获取值文本Id(GV);
        if (DSOLocalEquivalents.具有(键)) {
            return DSOLocalEquivalents.获取(键);
        }
        DSOLocalEquivalent Val = new DSOLocalEquivalent(GV);
        DSOLocalEquivalents.p·设置(键, Val);
        return DSOLocalEquivalents.获取(键);
    }
    static InlineAsm s·InlineAsm_get(InlineAsm asmV) {
        dstring 键 = asmV.AsmString ~ asmV.Constraints ~ ·to!(dstring)(asmV.HasSideEffects) ~ .获取类型文本Id(asmV.FTy) ~ ·to!(dstring)(asmV.IsAlignStack) ~ ·to!(dstring)(asmV.Dialect) ~ ·to!(dstring)(asmV.CanThrow);
        if (InlineAsms.具有(键)) {
            return InlineAsms.获取(键);
        }
        InlineAsms.p·设置(键, asmV);
        return InlineAsms.获取(键);
    }
}
class TGet_ {
    this() { }
    static 整数类型_ s·IntTy_get(uint 位数) {
        dstring 键 = ·to!(dstring)(位数);
        if (整数类型集合.具有(键)) {
            return 整数类型集合.获取(键);
        }
        整数类型_ t = new 整数类型_(位数);
        .获取类型Id(t);
        整数类型集合.p·设置(键, t);
        return 整数类型集合.获取(键);
    }
    static 指针类型_ s·PtrTy_get(类型_ t, uint 地址 = ··null!(uint)) {
        dstring 键 = (t !is ··null!(类型_)) ? .获取类型文本Id(t) ~ (地址 != 0 ? "-"d ~ ·to!(dstring)(地址) : ""d) : (地址 != 0 ? "-"d ~ ·to!(dstring)(地址) : ""d);
        if ((地址 is ··null!(uint)) || 地址 == 0) {
            if (PointerTypes.具有(键)) {
                return PointerTypes.获取(键);
            }
            指针类型_ pt = new 指针类型_(t, 0);
            .获取类型Id(pt);
            PointerTypes.p·设置(键, pt);
            return PointerTypes.获取(键);
        }
        else {
            if (ASPointerTypes.具有(键)) {
                return ASPointerTypes.获取(键);
            }
            指针类型_ pt = new 指针类型_(t, 地址);
            .获取类型Id(pt);
            ASPointerTypes.p·设置(键, pt);
            return ASPointerTypes.获取(键);
        }
    }
    static 函数类型_ s·FuncTy_get(类型_ 返回类型, 类型_[] 参数组, bool IsVarArg) {
        dstring 键 = .获取类型文本Id(返回类型);
        if (参数组.length > 0) {
            键 ~= "-"d ~ .获取类型列表的文本Id(参数组);
        }
        if (IsVarArg) {
            键 ~= "-"d ~ "IsVarArg"d;
        }
        if (FunctionTypes.具有(键)) {
            return FunctionTypes.获取(键);
        }
        函数类型_ pt = new 函数类型_(返回类型, 参数组, IsVarArg);
        .获取类型Id(pt);
        FunctionTypes.p·设置(键, pt);
        return FunctionTypes.获取(键);
    }
    static 向量类型_ s·VTy_get(类型_ 元素类型, bool 可扩展的, uint 数量) {
        dstring 键 = (.获取类型文本Id(元素类型) ~ "-"d).·to!(dstring)() ~ (可扩展的 ? "真"d : "假"d) ~ "-"d ~ ·to!(dstring)(数量);
        if (VectorTypes.具有(键)) {
            return VectorTypes.获取(键);
        }
        向量类型_ t = new 向量类型_(元素类型, 可扩展的, 数量);
        .获取类型Id(t);
        VectorTypes.p·设置(键, t);
        return VectorTypes.获取(键);
    }
    static 向量类型_ s·VTy_get(类型_ 元素类型, ElementCount 数量) {
        dstring 键 = (.获取类型文本Id(元素类型) ~ "-"d).·to!(dstring)() ~ (数量.isScalable() ? "真"d : "假"d) ~ "-"d ~ ·to!(dstring)(数量.getValue());
        if (VectorTypes.具有(键)) {
            return VectorTypes.获取(键);
        }
        向量类型_ t = new 向量类型_(元素类型, 数量.isScalable(), 数量.getValue());
        .获取类型Id(t);
        VectorTypes.p·设置(键, t);
        return VectorTypes.获取(键);
    }
    static 数组类型_ s·ArrTy_get(类型_ 元素类型, ulong 数量) {
        dstring 键 = .获取类型文本Id(元素类型) ~ "-"d ~ ·to!(dstring)(数量);
        if (ArrayTypes.具有(键)) {
            return ArrayTypes.获取(键);
        }
        数组类型_ t = new 数组类型_(元素类型, 数量);
        .获取类型Id(t);
        ArrayTypes.p·设置(键, t);
        return ArrayTypes.获取(键);
    }
    static 结构类型_ s·STy_get(符号_ 符号, bool 是压缩的 = false) {
        if (符号 is ··null!(符号_)) {
            return .不透明结构类型;
        }
        if (符号.类型 !is ··null!(类型_)) {
            结构类型_ ···temp·0·_4 = (cast(结构类型_)(符号.类型));
            assert((···temp·0·_4 !is ··null!(结构类型_)) && (cast(结构类型_)(符号.类型)).是压缩的 == 是压缩的, "符号错误"c);
            return (cast(结构类型_)(符号.类型));
        }
        结构类型_ t = new 结构类型_(符号, 是压缩的);
        .获取类型Id(t);
        .解析类型成员组(t);
        dstring id = .获取类型列表的文本Id(t.ContainedTys);
        if (AnonStructTypes.具有(id)) {
            结构类型_ ast = AnonStructTypes.获取(id);
            if (ast != t) {
                ast.符号 = 符号;
                ast.成员已解析 = true;
                符号.类型 = ast;
                return ast;
            }
        }
        else {
            AnonStructTypes.p·设置(id, t);
        }
        符号.类型 = t;
        return t;
    }
    static 结构类型_ s·STy_get(类型_[] Tys) {
        dstring id = .获取类型列表的文本Id(Tys);
        if (AnonStructTypes.具有(id)) {
            return AnonStructTypes.获取(id);
        }
        结构类型_ S = new 结构类型_();
        S.成员已解析 = true;
        S.ContainedTys = Tys;
        AnonStructTypes.p·设置(id, S);
        return AnonStructTypes.获取(id);
    }
}
class CExp_ {
    this() { }
    static bool s·isBinaryOp(uint Opcode) {
        return Opcode >= InstructionKind_.BinaryOpsBegin && Opcode < InstructionKind_.BinaryOpsEnd;
    }
    static bool s·isIntDivRem(uint Opcode) {
        return Opcode == InstructionKind_.UDiv || Opcode == InstructionKind_.SDiv || Opcode == InstructionKind_.URem || Opcode == InstructionKind_.SRem;
    }
    static bool s·isAssociative(uint Opcode) {
        return Opcode == InstructionKind_.And || Opcode == InstructionKind_.Or || Opcode == InstructionKind_.Xor || Opcode == InstructionKind_.Add || Opcode == InstructionKind_.Mul;
    }
    static bool s·isCommutative(uint Opcode) {
        switch (Opcode) {
            case InstructionKind_.Add:
            case InstructionKind_.FAdd:
            case InstructionKind_.Mul:
            case InstructionKind_.FMul:
            case InstructionKind_.And:
            case InstructionKind_.Or:
            case InstructionKind_.Xor: {
                return true;
            }
            default: break;
        }
        return false;
    }
    static bool s·hasIndices(ConstantExpr ex) {
        return ex.Opc == InstructionKind_.ExtractValue || ex.Opc == InstructionKind_.InsertValue;
    }
    static uint[] s·getIndices(ConstantExpr ex) {
        ExtractValueConstantExpr EVCE = .dyn_cast!(ExtractValueConstantExpr)(ex);
        if (EVCE !is ··null!(ExtractValueConstantExpr)) {
            return EVCE.Indices;
        }
        return .cast_!(InsertValueConstantExpr)(ex).Indices;
    }
    static uint s·getPredicate(ConstantExpr ex) {
        return .cast_!(CompareConstantExpr)(ex).predicate;
    }
    static int[] s·getShuffleMask(ConstantExpr ex) {
        return .cast_!(ShuffleVectorConstantExpr)(ex).Mask;
    }
    static bool s·isCast(ConstantExpr ex) {
        return ex.Opc >= InstructionKind_.CastOpsBegin && ex.Opc < InstructionKind_.CastOpsEnd;
    }
    static bool s·isGEPWithNoNotionalOverIndexing(ConstantExpr gep) {
        if (gep.Opc != InstructionKind_.GetElementPtr) {
            return false;
        }
        // The remaining indices may be compile-time known integers within the bounds
        // of the corresponding notional static array types.
        long NumElements = -1;
        类型_ CurTy = (cast(GetElementPtrConstantExpr)(gep)).SrcElementTy;
        {
            for (int i = 1; i < gep.Ops.length; ++i) {
                Value IO = gep.Ops[i];
                if (CurTy.种类 == TypeID_.ArrayTyID) {
                    NumElements = (cast(数组类型_)(CurTy)).数量;
                }
                else if (CurTy.种类 == TypeID_.FixedVectorTyID) {
                    NumElements = (cast(向量类型_)(CurTy)).数量;
                }
                else if (CurTy.种类 == TypeID_.ScalableVectorTyID) {
                    NumElements = -1;
                }
                CurTy = GEP_.s·getTypeAtIndex(CurTy, IO);
                ConstantInt CI = .dyn_cast!(ConstantInt)(IO);
                if ((CI is ··null!(ConstantInt)) || CurTy.种类 != TypeID_.StructTyID && NumElements != -1 && (CI.Val.getActiveBits() > 64 || CI.Val.getZExtValue() >= NumElements)) {
                    return false;
                }
            }
        }
        // All the indices checked out.
        return true;
    }
    static Constant s·getBinOpIdentity(uint Opcode, 类型_ Ty, bool AllowRHSConstant) {
        assert(CExp_.s·isBinaryOp(Opcode), "Only binops allowed"c);
        // Commutative opcodes: it does not matter 如果 AllowRHSConstant is set.
        if (CExp_.s·isCommutative(Opcode)) {
            switch (Opcode) {
                case InstructionKind_.Add: // X + 0 = X
                case InstructionKind_.Or: // X | 0 = X
                case InstructionKind_.Xor: {
                    return CGet_.s·getNullValue(Ty);
                }
                case InstructionKind_.Mul: {
                    return CGet_.s·CInt_get(Ty, 1, false);
                }
                case InstructionKind_.And: {
                    return .getAllOnesValue(Ty);
                }
                case InstructionKind_.FAdd: {
                    // TODO: If the fadd has 'nsz', should we 返回 +0.0?
                    return CGet_.s·CFP_getNegativeZero(Ty);
                }
                case InstructionKind_.FMul: {
                    return CGet_.s·CFP_get(Ty, 1.0);
                }
                default: {
                    assert(false, "Every commutative binop has an identity constant"c);
                }
            }
            return ··null!(Constant);
        }
        // Non-commutative opcodes: AllowRHSConstant must be set.
        if (!AllowRHSConstant) {
            return ··null!(Constant);
        }
        switch (Opcode) {
            case InstructionKind_.Sub: // X - 0 = X
            case InstructionKind_.Shl: // X << 0 = X
            case InstructionKind_.LShr: // X >>u 0 = X
            case InstructionKind_.AShr: // X >> 0 = X
            case InstructionKind_.FSub: {
                return CGet_.s·getNullValue(Ty);
            }
            case InstructionKind_.SDiv: // X / 1 = X
            case InstructionKind_.UDiv: {
                return CGet_.s·CInt_get(Ty, 1, false);
            }
            case InstructionKind_.FDiv: {
                return CGet_.s·CFP_get(Ty, 1.0);
            }
            default: break;
        }
        return ··null!(Constant);
    }
    static Constant s·getBinOpAbsorber(uint Opcode, 类型_ Ty) {
        switch (Opcode) {
            case InstructionKind_.Or: {
                return .getAllOnesValue(Ty);
            }
            case InstructionKind_.And:
            case InstructionKind_.Mul: {
                return CGet_.s·getNullValue(Ty);
            }
            default: break;
        }
        // Doesn't have an absorber.
        return ··null!(Constant);
    }
}
class CmpInst_ {
    this() { }
    static bool s·isIntPredicate(CmpInst_Predicate_ P) {
        return P >= CmpInst_Predicate_.FIRST_ICMP_PREDICATE && P <= CmpInst_Predicate_.LAST_ICMP_PREDICATE;
    }
    static bool s·isEquality(CmpInst_Predicate_ P) {
        return P == CmpInst_Predicate_.ICMP_EQ || P == CmpInst_Predicate_.ICMP_NE;
    }
    static CmpInst_Predicate_ s·getInversePredicate(CmpInst_Predicate_ pred) {
        switch (pred) {
            case CmpInst_Predicate_.ICMP_EQ: {
                return CmpInst_Predicate_.ICMP_NE;
            }
            case CmpInst_Predicate_.ICMP_NE: {
                return CmpInst_Predicate_.ICMP_EQ;
            }
            case CmpInst_Predicate_.ICMP_UGT: {
                return CmpInst_Predicate_.ICMP_ULE;
            }
            case CmpInst_Predicate_.ICMP_ULT: {
                return CmpInst_Predicate_.ICMP_UGE;
            }
            case CmpInst_Predicate_.ICMP_UGE: {
                return CmpInst_Predicate_.ICMP_ULT;
            }
            case CmpInst_Predicate_.ICMP_ULE: {
                return CmpInst_Predicate_.ICMP_UGT;
            }
            case CmpInst_Predicate_.ICMP_SGT: {
                return CmpInst_Predicate_.ICMP_SLE;
            }
            case CmpInst_Predicate_.ICMP_SLT: {
                return CmpInst_Predicate_.ICMP_SGE;
            }
            case CmpInst_Predicate_.ICMP_SGE: {
                return CmpInst_Predicate_.ICMP_SLT;
            }
            case CmpInst_Predicate_.ICMP_SLE: {
                return CmpInst_Predicate_.ICMP_SGT;
            }
            case CmpInst_Predicate_.FCMP_OEQ: {
                return CmpInst_Predicate_.FCMP_UNE;
            }
            case CmpInst_Predicate_.FCMP_ONE: {
                return CmpInst_Predicate_.FCMP_UEQ;
            }
            case CmpInst_Predicate_.FCMP_OGT: {
                return CmpInst_Predicate_.FCMP_ULE;
            }
            case CmpInst_Predicate_.FCMP_OLT: {
                return CmpInst_Predicate_.FCMP_UGE;
            }
            case CmpInst_Predicate_.FCMP_OGE: {
                return CmpInst_Predicate_.FCMP_ULT;
            }
            case CmpInst_Predicate_.FCMP_OLE: {
                return CmpInst_Predicate_.FCMP_UGT;
            }
            case CmpInst_Predicate_.FCMP_UEQ: {
                return CmpInst_Predicate_.FCMP_ONE;
            }
            case CmpInst_Predicate_.FCMP_UNE: {
                return CmpInst_Predicate_.FCMP_OEQ;
            }
            case CmpInst_Predicate_.FCMP_UGT: {
                return CmpInst_Predicate_.FCMP_OLE;
            }
            case CmpInst_Predicate_.FCMP_ULT: {
                return CmpInst_Predicate_.FCMP_OGE;
            }
            case CmpInst_Predicate_.FCMP_UGE: {
                return CmpInst_Predicate_.FCMP_OLT;
            }
            case CmpInst_Predicate_.FCMP_ULE: {
                return CmpInst_Predicate_.FCMP_OGT;
            }
            case CmpInst_Predicate_.FCMP_ORD: {
                return CmpInst_Predicate_.FCMP_UNO;
            }
            case CmpInst_Predicate_.FCMP_UNO: {
                return CmpInst_Predicate_.FCMP_ORD;
            }
            case CmpInst_Predicate_.FCMP_TRUE: {
                return CmpInst_Predicate_.FCMP_FALSE;
            }
            case CmpInst_Predicate_.FCMP_FALSE: {
                return CmpInst_Predicate_.FCMP_TRUE;
            }
            default: {
                assert(false, "Unknown cmp predicate!"c);
                return pred;
            }
        }
    }
    static CmpInst_Predicate_ s·getSwappedPredicate(CmpInst_Predicate_ pred) {
        switch (pred) {
            case CmpInst_Predicate_.ICMP_EQ:
            case CmpInst_Predicate_.ICMP_NE: {
                return pred;
            }
            case CmpInst_Predicate_.ICMP_SGT: {
                return CmpInst_Predicate_.ICMP_SLT;
            }
            case CmpInst_Predicate_.ICMP_SLT: {
                return CmpInst_Predicate_.ICMP_SGT;
            }
            case CmpInst_Predicate_.ICMP_SGE: {
                return CmpInst_Predicate_.ICMP_SLE;
            }
            case CmpInst_Predicate_.ICMP_SLE: {
                return CmpInst_Predicate_.ICMP_SGE;
            }
            case CmpInst_Predicate_.ICMP_UGT: {
                return CmpInst_Predicate_.ICMP_ULT;
            }
            case CmpInst_Predicate_.ICMP_ULT: {
                return CmpInst_Predicate_.ICMP_UGT;
            }
            case CmpInst_Predicate_.ICMP_UGE: {
                return CmpInst_Predicate_.ICMP_ULE;
            }
            case CmpInst_Predicate_.ICMP_ULE: {
                return CmpInst_Predicate_.ICMP_UGE;
            }
            case CmpInst_Predicate_.FCMP_FALSE:
            case CmpInst_Predicate_.FCMP_TRUE:
            case CmpInst_Predicate_.FCMP_OEQ:
            case CmpInst_Predicate_.FCMP_ONE:
            case CmpInst_Predicate_.FCMP_UEQ:
            case CmpInst_Predicate_.FCMP_UNE:
            case CmpInst_Predicate_.FCMP_ORD:
            case CmpInst_Predicate_.FCMP_UNO: {
                return pred;
            }
            case CmpInst_Predicate_.FCMP_OGT: {
                return CmpInst_Predicate_.FCMP_OLT;
            }
            case CmpInst_Predicate_.FCMP_OLT: {
                return CmpInst_Predicate_.FCMP_OGT;
            }
            case CmpInst_Predicate_.FCMP_OGE: {
                return CmpInst_Predicate_.FCMP_OLE;
            }
            case CmpInst_Predicate_.FCMP_OLE: {
                return CmpInst_Predicate_.FCMP_OGE;
            }
            case CmpInst_Predicate_.FCMP_UGT: {
                return CmpInst_Predicate_.FCMP_ULT;
            }
            case CmpInst_Predicate_.FCMP_ULT: {
                return CmpInst_Predicate_.FCMP_UGT;
            }
            case CmpInst_Predicate_.FCMP_UGE: {
                return CmpInst_Predicate_.FCMP_ULE;
            }
            case CmpInst_Predicate_.FCMP_ULE: {
                return CmpInst_Predicate_.FCMP_UGE;
            }
            default: {
                assert(false, "Unknown cmp predicate!"c);
                return pred;
            }
        }
    }
    static bool s·isNonStrictPredicate(CmpInst_Predicate_ pred) {
        switch (pred) {
            case CmpInst_Predicate_.ICMP_SGE:
            case CmpInst_Predicate_.ICMP_SLE:
            case CmpInst_Predicate_.ICMP_UGE:
            case CmpInst_Predicate_.ICMP_ULE:
            case CmpInst_Predicate_.FCMP_OGE:
            case CmpInst_Predicate_.FCMP_OLE:
            case CmpInst_Predicate_.FCMP_UGE:
            case CmpInst_Predicate_.FCMP_ULE: {
                return true;
            }
            default: {
                return false;
            }
        }
    }
    static bool s·isStrictPredicate(CmpInst_Predicate_ pred) {
        switch (pred) {
            case CmpInst_Predicate_.ICMP_SGT:
            case CmpInst_Predicate_.ICMP_SLT:
            case CmpInst_Predicate_.ICMP_UGT:
            case CmpInst_Predicate_.ICMP_ULT:
            case CmpInst_Predicate_.FCMP_OGT:
            case CmpInst_Predicate_.FCMP_OLT:
            case CmpInst_Predicate_.FCMP_UGT:
            case CmpInst_Predicate_.FCMP_ULT: {
                return true;
            }
            default: {
                return false;
            }
        }
    }
    static CmpInst_Predicate_ s·getStrictPredicate(CmpInst_Predicate_ pred) {
        switch (pred) {
            case CmpInst_Predicate_.ICMP_SGE: {
                return CmpInst_Predicate_.ICMP_SGT;
            }
            case CmpInst_Predicate_.ICMP_SLE: {
                return CmpInst_Predicate_.ICMP_SLT;
            }
            case CmpInst_Predicate_.ICMP_UGE: {
                return CmpInst_Predicate_.ICMP_UGT;
            }
            case CmpInst_Predicate_.ICMP_ULE: {
                return CmpInst_Predicate_.ICMP_ULT;
            }
            case CmpInst_Predicate_.FCMP_OGE: {
                return CmpInst_Predicate_.FCMP_OGT;
            }
            case CmpInst_Predicate_.FCMP_OLE: {
                return CmpInst_Predicate_.FCMP_OLT;
            }
            case CmpInst_Predicate_.FCMP_UGE: {
                return CmpInst_Predicate_.FCMP_UGT;
            }
            case CmpInst_Predicate_.FCMP_ULE: {
                return CmpInst_Predicate_.FCMP_ULT;
            }
            default: {
                return pred;
            }
        }
    }
    static CmpInst_Predicate_ s·getNonStrictPredicate(CmpInst_Predicate_ pred) {
        switch (pred) {
            case CmpInst_Predicate_.ICMP_SGT: {
                return CmpInst_Predicate_.ICMP_SGE;
            }
            case CmpInst_Predicate_.ICMP_SLT: {
                return CmpInst_Predicate_.ICMP_SLE;
            }
            case CmpInst_Predicate_.ICMP_UGT: {
                return CmpInst_Predicate_.ICMP_UGE;
            }
            case CmpInst_Predicate_.ICMP_ULT: {
                return CmpInst_Predicate_.ICMP_ULE;
            }
            case CmpInst_Predicate_.FCMP_OGT: {
                return CmpInst_Predicate_.FCMP_OGE;
            }
            case CmpInst_Predicate_.FCMP_OLT: {
                return CmpInst_Predicate_.FCMP_OLE;
            }
            case CmpInst_Predicate_.FCMP_UGT: {
                return CmpInst_Predicate_.FCMP_UGE;
            }
            case CmpInst_Predicate_.FCMP_ULT: {
                return CmpInst_Predicate_.FCMP_ULE;
            }
            default: {
                return pred;
            }
        }
    }
    static CmpInst_Predicate_ s·getFlippedStrictnessPredicate(CmpInst_Predicate_ pred) {
        if (CmpInst_.s·isStrictPredicate(pred)) {
            return CmpInst_.s·getNonStrictPredicate(pred);
        }
        if (CmpInst_.s·isNonStrictPredicate(pred)) {
            return CmpInst_.s·getStrictPredicate(pred);
        }
        assert(false, "Unknown predicate!"c);
        return CmpInst_Predicate_.FCMP_FALSE;
    }
    static CmpInst_Predicate_ s·getSignedPredicate(CmpInst_Predicate_ pred) {
        switch (pred) {
            case CmpInst_Predicate_.ICMP_ULT: {
                return CmpInst_Predicate_.ICMP_SLT;
            }
            case CmpInst_Predicate_.ICMP_ULE: {
                return CmpInst_Predicate_.ICMP_SLE;
            }
            case CmpInst_Predicate_.ICMP_UGT: {
                return CmpInst_Predicate_.ICMP_SGT;
            }
            case CmpInst_Predicate_.ICMP_UGE: {
                return CmpInst_Predicate_.ICMP_SGE;
            }
            default: {
                assert(false, "Unknown predicate!"c);
            }
        }
        return CmpInst_Predicate_.FCMP_FALSE;
    }
    static CmpInst_Predicate_ s·getUnsignedPredicate(CmpInst_Predicate_ pred) {
        switch (pred) {
            case CmpInst_Predicate_.ICMP_SLT: {
                return CmpInst_Predicate_.ICMP_ULT;
            }
            case CmpInst_Predicate_.ICMP_SLE: {
                return CmpInst_Predicate_.ICMP_ULE;
            }
            case CmpInst_Predicate_.ICMP_SGT: {
                return CmpInst_Predicate_.ICMP_UGT;
            }
            case CmpInst_Predicate_.ICMP_SGE: {
                return CmpInst_Predicate_.ICMP_UGE;
            }
            default: {
                assert(false, "Unknown predicate!"c);
            }
        }
        return CmpInst_Predicate_.FCMP_FALSE;
    }
    static CmpInst_Predicate_ s·getSignedPredicate_I(CmpInst_Predicate_ pred) {
        switch (pred) {
            case CmpInst_Predicate_.ICMP_EQ:
            case CmpInst_Predicate_.ICMP_NE:
            case CmpInst_Predicate_.ICMP_SGT:
            case CmpInst_Predicate_.ICMP_SLT:
            case CmpInst_Predicate_.ICMP_SGE:
            case CmpInst_Predicate_.ICMP_SLE: {
                return pred;
            }
            case CmpInst_Predicate_.ICMP_UGT: {
                return CmpInst_Predicate_.ICMP_SGT;
            }
            case CmpInst_Predicate_.ICMP_ULT: {
                return CmpInst_Predicate_.ICMP_SLT;
            }
            case CmpInst_Predicate_.ICMP_UGE: {
                return CmpInst_Predicate_.ICMP_SGE;
            }
            case CmpInst_Predicate_.ICMP_ULE: {
                return CmpInst_Predicate_.ICMP_SLE;
            }
            default: {
                assert(false, "Unknown icmp predicate!"c);
            }
        }
        return CmpInst_Predicate_.FCMP_FALSE;
    }
    static CmpInst_Predicate_ s·getUnsignedPredicate_I(CmpInst_Predicate_ pred) {
        switch (pred) {
            case CmpInst_Predicate_.ICMP_EQ:
            case CmpInst_Predicate_.ICMP_NE:
            case CmpInst_Predicate_.ICMP_UGT:
            case CmpInst_Predicate_.ICMP_ULT:
            case CmpInst_Predicate_.ICMP_UGE:
            case CmpInst_Predicate_.ICMP_ULE: {
                return pred;
            }
            case CmpInst_Predicate_.ICMP_SGT: {
                return CmpInst_Predicate_.ICMP_UGT;
            }
            case CmpInst_Predicate_.ICMP_SLT: {
                return CmpInst_Predicate_.ICMP_ULT;
            }
            case CmpInst_Predicate_.ICMP_SGE: {
                return CmpInst_Predicate_.ICMP_UGE;
            }
            case CmpInst_Predicate_.ICMP_SLE: {
                return CmpInst_Predicate_.ICMP_ULE;
            }
            default: {
                assert(false, "Unknown icmp predicate!"c);
                return pred;
            }
        }
    }
    static bool s·isUnsigned(CmpInst_Predicate_ predicate) {
        switch (predicate) {
            case CmpInst_Predicate_.ICMP_ULT:
            case CmpInst_Predicate_.ICMP_ULE:
            case CmpInst_Predicate_.ICMP_UGT:
            case CmpInst_Predicate_.ICMP_UGE: {
                return true;
            }
            default: {
                return false;
            }
        }
    }
    static bool s·isSigned(CmpInst_Predicate_ predicate) {
        switch (predicate) {
            case CmpInst_Predicate_.ICMP_SLT:
            case CmpInst_Predicate_.ICMP_SLE:
            case CmpInst_Predicate_.ICMP_SGT:
            case CmpInst_Predicate_.ICMP_SGE: {
                return true;
            }
            default: {
                return false;
            }
        }
    }
    static CmpInst_Predicate_ s·getFlippedSignednessPredicate(CmpInst_Predicate_ pred) {
        if (CmpInst_.s·isSigned(pred)) {
            return CmpInst_.s·getUnsignedPredicate(pred);
        }
        if (CmpInst_.s·isUnsigned(pred)) {
            return CmpInst_.s·getSignedPredicate(pred);
        }
        assert(false, "Unknown predicate!"c);
        return CmpInst_Predicate_.FCMP_FALSE;
    }
    static bool s·isOrdered(CmpInst_Predicate_ predicate) {
        switch (predicate) {
            case CmpInst_Predicate_.FCMP_OEQ:
            case CmpInst_Predicate_.FCMP_ONE:
            case CmpInst_Predicate_.FCMP_OGT:
            case CmpInst_Predicate_.FCMP_OLT:
            case CmpInst_Predicate_.FCMP_OGE:
            case CmpInst_Predicate_.FCMP_OLE:
            case CmpInst_Predicate_.FCMP_ORD: {
                return true;
            }
            default: {
                return false;
            }
        }
    }
    static bool s·isUnordered(CmpInst_Predicate_ predicate) {
        switch (predicate) {
            case CmpInst_Predicate_.FCMP_UEQ:
            case CmpInst_Predicate_.FCMP_UNE:
            case CmpInst_Predicate_.FCMP_UGT:
            case CmpInst_Predicate_.FCMP_ULT:
            case CmpInst_Predicate_.FCMP_UGE:
            case CmpInst_Predicate_.FCMP_ULE:
            case CmpInst_Predicate_.FCMP_UNO: {
                return true;
            }
            default: {
                return false;
            }
        }
    }
    static bool s·isTrueWhenEqual(CmpInst_Predicate_ predicate) {
        switch (predicate) {
            case CmpInst_Predicate_.ICMP_EQ:
            case CmpInst_Predicate_.ICMP_UGE:
            case CmpInst_Predicate_.ICMP_ULE:
            case CmpInst_Predicate_.ICMP_SGE:
            case CmpInst_Predicate_.ICMP_SLE:
            case CmpInst_Predicate_.FCMP_TRUE:
            case CmpInst_Predicate_.FCMP_UEQ:
            case CmpInst_Predicate_.FCMP_UGE:
            case CmpInst_Predicate_.FCMP_ULE: {
                return true;
            }
            default: {
                return false;
            }
        }
    }
    static bool s·isFalseWhenEqual(CmpInst_Predicate_ predicate) {
        switch (predicate) {
            case CmpInst_Predicate_.ICMP_NE:
            case CmpInst_Predicate_.ICMP_UGT:
            case CmpInst_Predicate_.ICMP_ULT:
            case CmpInst_Predicate_.ICMP_SGT:
            case CmpInst_Predicate_.ICMP_SLT:
            case CmpInst_Predicate_.FCMP_FALSE:
            case CmpInst_Predicate_.FCMP_ONE:
            case CmpInst_Predicate_.FCMP_OGT:
            case CmpInst_Predicate_.FCMP_OLT: {
                return true;
            }
            default: {
                return false;
            }
        }
    }
    static bool s·isImpliedTrueByMatchingCmp(CmpInst_Predicate_ Pred1, CmpInst_Predicate_ Pred2) {
        // If the predicates match, then we know the first condition implies the
        // second is 真.
        if (Pred1 == Pred2) {
            return true;
        }
        switch (Pred1) {
            case CmpInst_Predicate_.ICMP_EQ: {
                // A == B implies A >=u B, A <=u B, A >=s B, and A <=s B are 真.
                return Pred2 == CmpInst_Predicate_.ICMP_UGE || Pred2 == CmpInst_Predicate_.ICMP_ULE || Pred2 == CmpInst_Predicate_.ICMP_SGE || Pred2 == CmpInst_Predicate_.ICMP_SLE;
            }
            case CmpInst_Predicate_.ICMP_UGT: {
                return Pred2 == CmpInst_Predicate_.ICMP_NE || Pred2 == CmpInst_Predicate_.ICMP_UGE;
            }
            case CmpInst_Predicate_.ICMP_ULT: {
                return Pred2 == CmpInst_Predicate_.ICMP_NE || Pred2 == CmpInst_Predicate_.ICMP_ULE;
            }
            case CmpInst_Predicate_.ICMP_SGT: {
                return Pred2 == CmpInst_Predicate_.ICMP_NE || Pred2 == CmpInst_Predicate_.ICMP_SGE;
            }
            case CmpInst_Predicate_.ICMP_SLT: {
                return Pred2 == CmpInst_Predicate_.ICMP_NE || Pred2 == CmpInst_Predicate_.ICMP_SLE;
            }
            default: {
                break;
            }
        }
        return false;
    }
    static bool s·isImpliedFalseByMatchingCmp(CmpInst_Predicate_ Pred1, CmpInst_Predicate_ Pred2) {
        return CmpInst_.s·isImpliedTrueByMatchingCmp(Pred1, CmpInst_.s·getInversePredicate(Pred2));
    }
    static bool s·isFPPredicate(CmpInst_Predicate_ P) {
        return P <= CmpInst_Predicate_.LAST_FCMP_PREDICATE;
    }
    static CmpInst_Predicate_ s·evaluateFCmpRelation(Constant V1, Constant V2) {
        assert(V1.类型 == V2.类型, "Cannot compare values of different types!"c);
        // We do not know 如果 a constant expression will evaluate to a number or NaN.
        // Therefore, we can only say that the relation is unordered or equal.
        if (V1 == V2) {
            return CmpInst_Predicate_.FCMP_UEQ;
        }
        if (!.isConstantExpr(V1)) {
            if (!.isConstantExpr(V2)) {
                // Simple 若是, use the standard constant folder.
                ConstantInt R = 返回零值!(ConstantInt)();
                R = .dyn_cast!(ConstantInt)(CEGet_.s·getFCmp(CmpInst_Predicate_.FCMP_OEQ, V1, V2));
                if ((R !is ··null!(ConstantInt)) && !R.Val.isZero()) {
                    return CmpInst_Predicate_.FCMP_OEQ;
                }
                R = .dyn_cast!(ConstantInt)(CEGet_.s·getFCmp(CmpInst_Predicate_.FCMP_OLT, V1, V2));
                if ((R !is ··null!(ConstantInt)) && !R.Val.isZero()) {
                    return CmpInst_Predicate_.FCMP_OLT;
                }
                R = .dyn_cast!(ConstantInt)(CEGet_.s·getFCmp(CmpInst_Predicate_.FCMP_OGT, V1, V2));
                if ((R !is ··null!(ConstantInt)) && !R.Val.isZero()) {
                    return CmpInst_Predicate_.FCMP_OGT;
                }
                // Nothing more we can do
                return CmpInst_Predicate_.BAD_FCMP_PREDICATE;
            }
            // If the first operand is simple and second is ConstantExpr, swap operands.
            CmpInst_Predicate_ SwappedRelation = CmpInst_.s·evaluateFCmpRelation(V2, V1);
            if (SwappedRelation != CmpInst_Predicate_.BAD_FCMP_PREDICATE) {
                return CmpInst_.s·getSwappedPredicate(SwappedRelation);
            }
        }
        else {
            // Ok, the LHS is known to be a constantexpr.  The RHS can be any of a
            // constantexpr or a simple constant.
            ConstantExpr CE1 = .cast_!(ConstantExpr)(V1);
            switch (CE1.Opc) {
                case InstructionKind_.FPTrunc:
                case InstructionKind_.FPExt:
                case InstructionKind_.UIToFP:
                case InstructionKind_.SIToFP: {
                    // We might be able to do something with these but we don't right now.
                    break;
                }
                default: {
                    break;
                }
            }
        }
        // There are MANY other foldings that we could perform here.  They will
        // probably be added on demand, as they seem needed.
        return CmpInst_Predicate_.BAD_FCMP_PREDICATE;
    }
    static CmpInst_Predicate_ s·evaluateICmpRelation(Constant V1, Constant V2, bool isSigned) {
        assert(V1.类型 == V2.类型, "Cannot compare different types of values!"c);
        if (V1 == V2) {
            return CmpInst_Predicate_.ICMP_EQ;
        }
        if (!.isConstantExpr(V1) && !.isGlobalValue(V1) && !.isBlockAddress(V1)) {
            if (!.isGlobalValue(V2) && !.isConstantExpr(V2) && !.isBlockAddress(V2)) {
                // We distilled this down to a simple 若是, use the standard constant
                // folder.
                ConstantInt R = 返回零值!(ConstantInt)();
                CmpInst_Predicate_ pred = CmpInst_Predicate_.ICMP_EQ;
                R = .dyn_cast!(ConstantInt)(CEGet_.s·getICmp(pred, V1, V2));
                if ((R !is ··null!(ConstantInt)) && !R.Val.isZero()) {
                    return pred;
                }
                pred = isSigned ? CmpInst_Predicate_.ICMP_SLT : CmpInst_Predicate_.ICMP_ULT;
                R = .dyn_cast!(ConstantInt)(CEGet_.s·getICmp(pred, V1, V2));
                if ((R !is ··null!(ConstantInt)) && !R.Val.isZero()) {
                    return pred;
                }
                pred = isSigned ? CmpInst_Predicate_.ICMP_SGT : CmpInst_Predicate_.ICMP_UGT;
                R = .dyn_cast!(ConstantInt)(CEGet_.s·getICmp(pred, V1, V2));
                if ((R !is ··null!(ConstantInt)) && !R.Val.isZero()) {
                    return pred;
                }
                // If we couldn't figure it out, bail.
                return CmpInst_Predicate_.BAD_ICMP_PREDICATE;
            }
            // If the first operand is simple, swap operands.
            CmpInst_Predicate_ SwappedRelation = CmpInst_.s·evaluateICmpRelation(V2, V1, isSigned);
            if (SwappedRelation != CmpInst_Predicate_.BAD_ICMP_PREDICATE) {
                return CmpInst_.s·getSwappedPredicate(SwappedRelation);
            }
        }
        else if (.dyn_cast!(GlobalValue)(V1) !is ··null!(GlobalValue)) {
            GlobalValue GV = .dyn_cast!(GlobalValue)(V1);
            if (.isConstantExpr(V2)) { // Swap as necessary.
                CmpInst_Predicate_ SwappedRelation = CmpInst_.s·evaluateICmpRelation(V2, V1, isSigned);
                if (SwappedRelation != CmpInst_Predicate_.BAD_ICMP_PREDICATE) {
                    return CmpInst_.s·getSwappedPredicate(SwappedRelation);
                }
                return CmpInst_Predicate_.BAD_ICMP_PREDICATE;
            }
            // Now we know that the RHS is a GlobalValue, BlockAddress or simple
            // constant (which, since the types must match, means that it's a
            // ConstantPointerNull).
            GlobalValue GV2 = .dyn_cast!(GlobalValue)(V2);
            if (GV2 !is ··null!(GlobalValue)) {
                return GlobalValue_.s·areGlobalsPotentiallyEqual(GV, GV2);
            }
            else if (.isBlockAddress(V2)) {
                return CmpInst_Predicate_.ICMP_NE; // Globals never equal labels.
            }
            else {
                assert(.isConstantPointerNull(V2), "Canonicalization guarantee!"c);
                // GlobalVals can never be null unless they have external weak linkage.
                // We don't try to evaluate aliases here.
                // NOTE: We should not be doing this constant folding 如果 null pointer
                // is considered valid for the function. But currently there is no way to
                // query it from the Constant type.
                if (!.hasExternalWeakLinkage(GV) && !.isGlobalAlias(GV) && !.NullPointerIsDefined(返回零值!(Function)() /* F */, (cast(指针类型_)(GV.类型)).地址)) {
                    return CmpInst_Predicate_.ICMP_UGT;
                }
            }
        }
        else if (.dyn_cast!(BlockAddress)(V1) !is ··null!(BlockAddress)) {
            BlockAddress BA = .dyn_cast!(BlockAddress)(V1);
            if (.isConstantExpr(V2)) { // Swap as necessary.
                CmpInst_Predicate_ SwappedRelation = CmpInst_.s·evaluateICmpRelation(V2, V1, isSigned);
                if (SwappedRelation != CmpInst_Predicate_.BAD_ICMP_PREDICATE) {
                    return CmpInst_.s·getSwappedPredicate(SwappedRelation);
                }
                return CmpInst_Predicate_.BAD_ICMP_PREDICATE;
            }
            // Now we know that the RHS is a GlobalValue, BlockAddress or simple
            // constant (which, since the types must match, means that it is a
            // ConstantPointerNull).
            BlockAddress BA2 = .dyn_cast!(BlockAddress)(V2);
            if (BA2 !is ··null!(BlockAddress)) {
                // Block address in another function can't equal this one, but block
                // addresses in the current function might be the same 如果 blocks are
                // empty.
                if (BA2.FN != BA.FN) {
                    return CmpInst_Predicate_.ICMP_NE;
                }
            }
            else {
                // Block addresses aren't null, don't equal the address of globals.
                assert((.isConstantPointerNull(V2) || .isGlobalValue(V2)), "Canonicalization guarantee!"c);
                return CmpInst_Predicate_.ICMP_NE;
            }
        }
        else {
            // Ok, the LHS is known to be a constantexpr.  The RHS can be any of a
            // constantexpr, a global, block address, or a simple constant.
            ConstantExpr CE1 = .cast_!(ConstantExpr)(V1);
            Constant CE1Op0 = (cast(Constant)(CE1.Ops[0]));
            switch (CE1.Opc) {
                case InstructionKind_.Trunc:
                case InstructionKind_.FPTrunc:
                case InstructionKind_.FPExt:
                case InstructionKind_.FPToUI:
                case InstructionKind_.FPToSI: {
                    break;
                } // We can't evaluate floating point casts or truncations.
                case InstructionKind_.BitCast: {
                    // If this is a global value cast_, check to see 如果 the RHS is also a
                    // GlobalValue.
                    GlobalValue GV = .dyn_cast!(GlobalValue)(CE1Op0);
                    if (GV !is ··null!(GlobalValue)) {
                        GlobalValue GV2 = .dyn_cast!(GlobalValue)(V2);
                        if (GV2 !is ··null!(GlobalValue)) {
                            return GlobalValue_.s·areGlobalsPotentiallyEqual(GV, GV2);
                        }
                    }
                }
                case InstructionKind_.UIToFP:
                case InstructionKind_.SIToFP:
                case InstructionKind_.ZExt:
                case InstructionKind_.SExt: {
                    // We can't evaluate floating point casts or truncations.
                    if (.isFPOrFPVectorTy(CE1Op0.类型)) {
                        break;
                    }
                    // If the cast_ is not actually changing bits, and the second operand is a
                    // null pointer, do the comparison with the pre-casted value.
                    if (.isNullValue(V2) && .isIntOrPtrTy(CE1.类型)) {
                        if (CE1.Opc == InstructionKind_.ZExt) {
                            isSigned = false;
                        }
                        if (CE1.Opc == InstructionKind_.SExt) {
                            isSigned = true;
                        }
                        return CmpInst_.s·evaluateICmpRelation(CE1Op0, CGet_.s·getNullValue(CE1Op0.类型), isSigned);
                    }
                    break;
                }
                case InstructionKind_.GetElementPtr: {
                    GetElementPtrConstantExpr CE1GEP = .cast_!(GetElementPtrConstantExpr)(CE1);
                    // Ok, since this is a getelementptr, we know that the constant has a
                    // pointer type.  Check the various cases.
                    if (.isConstantPointerNull(V2)) {
                        // If we are comparing a GEP to a null pointer, check to see 如果 the base
                        // of the GEP equals the null pointer.
                        GlobalValue GV = .dyn_cast!(GlobalValue)(CE1Op0);
                        if (GV !is ··null!(GlobalValue)) {
                            // If its not weak linkage, the GVal must have a non-zero address
                            // so the result is greater-than
                            if (!.hasExternalWeakLinkage(GV)) {
                                return CmpInst_Predicate_.ICMP_UGT;
                            }
                        }
                        else if (.isConstantPointerNull(CE1Op0)) {
                            {
                                // If we are indexing from a null pointer, check to see 如果 we have any
                                // non-zero indices.
                                for (int i = 1; i < CE1.Ops.length; ++i) {
                                    if (!.isNullValue((cast(Constant)(CE1.Ops[1])))) {
                                        // Offsetting from null, must not be equal.
                                        return CmpInst_Predicate_.ICMP_UGT;
                                    }
                                }
                            }
                            // Only zero indexes from null, must still be zero.
                            return CmpInst_Predicate_.ICMP_EQ;
                        }
                    }
                    else if (.dyn_cast!(GlobalValue)(V2) !is ··null!(GlobalValue)) {
                        GlobalValue GV2 = .dyn_cast!(GlobalValue)(V2);
                        if (.isConstantPointerNull(CE1Op0)) {
                            // If its not weak linkage, the GVal must have a non-zero address
                            // so the result is less-than
                            if (!.hasExternalWeakLinkage(GV2)) {
                                return CmpInst_Predicate_.ICMP_ULT;
                            }
                        }
                        else if (.dyn_cast!(GlobalValue)(CE1Op0) !is ··null!(GlobalValue)) {
                            GlobalValue GV = .dyn_cast!(GlobalValue)(CE1Op0);
                            if (GV == GV2) {
                                // If this is a getelementptr of the same global, then it must be
                                // different.  Because the types must match, the getelementptr could
                                // only have at most one index, and because we fold getelementptr's
                                // with a single zero index, it must be nonzero.
                                assert(CE1.Ops.length == 2 && !.isNullValue((cast(Constant)(CE1.Ops[1]))), "Surprising getelementptr!"c);
                                return CmpInst_Predicate_.ICMP_UGT;
                            }
                            else {
                                if (GEP_.s·hasAllZeroIndices(CE1GEP)) {
                                    return GlobalValue_.s·areGlobalsPotentiallyEqual(GV, GV2);
                                }
                                return CmpInst_Predicate_.BAD_ICMP_PREDICATE;
                            }
                        }
                    }
                    else {
                        ConstantExpr CE2 = .cast_!(ConstantExpr)(V2);
                        Value CE2Op0 = CE2.Ops[0];
                        // There are MANY other foldings that we could perform here.  They will
                        // probably be added on demand, as they seem needed.
                        switch (CE2.Opc) {
                            case InstructionKind_.GetElementPtr: {
                                // By far the most common 若是 to handle is when the base pointers are
                                // obviously to the same global.
                                if (.isGlobalValue(CE1Op0) && .isGlobalValue(CE2Op0)) {
                                    // Don't know relative ordering, but check for inequality.
                                    if (CE1Op0 != CE2Op0) {
                                        GetElementPtrConstantExpr CE2GEP = .cast_!(GetElementPtrConstantExpr)(CE2);
                                        if (GEP_.s·hasAllZeroIndices(CE1GEP) && GEP_.s·hasAllZeroIndices(CE2GEP)) {
                                            return GlobalValue_.s·areGlobalsPotentiallyEqual(.cast_!(GlobalValue)(CE1Op0), .cast_!(GlobalValue)(CE2Op0));
                                        }
                                        return CmpInst_Predicate_.BAD_ICMP_PREDICATE;
                                    }
                                    // Ok, we know that both getelementptr instructions are based on the
                                    // same global.  From this, we can precisely determine the relative
                                    // ordering of the resultant pointers.
                                    int i = 1;
                                    // The logic below assumes that the result of the comparison
                                    // can be determined by finding the first index that differs.
                                    // This doesn't work 如果 there is over-indexing in any
                                    // subsequent indices, so check for that 若是 first.
                                    if (!CExp_.s·isGEPWithNoNotionalOverIndexing(CE1) || !CExp_.s·isGEPWithNoNotionalOverIndexing(CE2)) {
                                        return CmpInst_Predicate_.BAD_ICMP_PREDICATE;
                                    } // Might be equal.
                                    // Compare all of the operands the GEP's have in common.
                                    GetElementPtrConstantExpr GTI = .cast_!(GetElementPtrConstantExpr)(CE1);
                                    类型_ CurTy = (cast(GetElementPtrConstantExpr)(GTI)).SrcElementTy;
                                    for (; i != CE1.Ops.length && i != CE2.Ops.length; ++i) {
                                        CurTy = GEP_.s·getTypeAtIndex(CurTy, CE1.Ops[i]);
                                        switch (.IdxCompare((cast(Constant)(CE1.Ops[i])), (cast(Constant)(CE2.Ops[i])), CurTy)) {
                                            case -1: {
                                                return isSigned ? CmpInst_Predicate_.ICMP_SLT : CmpInst_Predicate_.ICMP_ULT;
                                            }
                                            case 1: {
                                                return isSigned ? CmpInst_Predicate_.ICMP_SGT : CmpInst_Predicate_.ICMP_UGT;
                                            }
                                            case -2: {
                                                return CmpInst_Predicate_.BAD_ICMP_PREDICATE;
                                            }
                                            default: break;
                                        }
                                    }
                                    // Ok, we ran out of things they have in common.  If any leftovers
                                    // are non-zero then we have a difference, otherwise we are equal.
                                    for (; i < CE1.Ops.length; ++i) {
                                        if (!.isNullValue((cast(Constant)(CE1.Ops[i])))) {
                                            if (.isConstantInt(CE1.Ops[i])) {
                                                return isSigned ? CmpInst_Predicate_.ICMP_SGT : CmpInst_Predicate_.ICMP_UGT;
                                            }
                                            else {
                                                return CmpInst_Predicate_.BAD_ICMP_PREDICATE;
                                            } // Might be equal.
                                        }
                                    }
                                    for (; i < CE2.Ops.length; ++i) {
                                        if (!.isNullValue((cast(Constant)(CE2.Ops[i])))) {
                                            if (.isConstantInt(CE2.Ops[i])) {
                                                return isSigned ? CmpInst_Predicate_.ICMP_SLT : CmpInst_Predicate_.ICMP_ULT;
                                            }
                                            else {
                                                return CmpInst_Predicate_.BAD_ICMP_PREDICATE;
                                            } // Might be equal.
                                        }
                                    }
                                    return CmpInst_Predicate_.ICMP_EQ;
                                }
                            }
                            default: {
                                break;
                            }
                        }
                    }
                    break;
                }
                default: {
                    break;
                }
            }
        }
        return CmpInst_Predicate_.BAD_ICMP_PREDICATE;
    }
}
class VTy_ {
    this() { }
    static ElementCount s·getElementCount(向量类型_ Ty) {
        return new ElementCount(Ty.数量, Ty.可扩展的);
    }
}
class PTy_ {
    this() { }
    static bool s·isOpaque(指针类型_ Pt) {
        return (Pt.类型) !is ··null!(类型_);
    }
    static bool s·isOpaqueOrPointeeTypeMatches(指针类型_ Pt, 类型_ Ty) {
        return PTy_.s·isOpaque(Pt) || Pt.类型 == Ty;
    }
    static bool s·hasSameElementTypeAs(指针类型_ Pt, 指针类型_ Other) {
        return Pt.类型 == Other.类型;
    }
    static bool s·isValidElementType(类型_ Ty) {
        return !.isVoidType(Ty) && !.isLabelTy(Ty) && !.isMetadataTy(Ty) && !.isTokenTy(Ty) && !.isX86_AMXTy(Ty) && !(.isPointerTy(Ty) && PTy_.s·isOpaque((cast(指针类型_)(Ty))));
    }
}
class ConstantExprKeyType {
    InstructionKind_ Opcode;
    ulong SubclassOptionalData;
    ushort SubclassData;
    Constant[] Ops;
    uint[] Indexes;
    int[] ShuffleMask;
    类型_ ExplicitTy;
    this() { }
    this(InstructionKind_ Opcode, Constant[] Ops, ushort SubclassData = ··null!(ushort), ubyte SubclassOptionalData = ··null!(ubyte), uint[] Indexes = ··null!(uint[]), int[] ShuffleMask = ··null!(int[]), 类型_ ExplicitTy = ··null!(类型_)) {
        this.Opcode = Opcode;
        this.SubclassOptionalData = SubclassOptionalData;
        this.SubclassData = SubclassData;
        this.Ops = Ops;
        this.Indexes = Indexes;
        this.ShuffleMask = ShuffleMask;
        this.ExplicitTy = ExplicitTy;
    }
    this(Constant[] Operands, ConstantExpr CE) {
        this.Opcode = CE.Opc;
        this.SubclassOptionalData = CE.SubclassOptionalData;
        this.SubclassData = .isCompare(CE) ? .getPredicate((cast(CompareConstantExpr)(CE))) : 0;
        this.Ops = Operands;
        this.Indexes = .getIndicesIfValid(CE);
        this.ShuffleMask = .getShuffleMaskIfValid(CE);
        this.ExplicitTy = .getSourceElementTypeIfValid(CE);
    }
    this(ConstantExpr CE, Constant[] Storage) {
        assert(Storage.length == 0, "Expected empty storage"c);
        this.Opcode = CE.Opc;
        this.SubclassOptionalData = CE.SubclassOptionalData;
        this.SubclassData = .isCompare(CE) ? .getPredicate((cast(CompareConstantExpr)(CE))) : 0;
        this.Indexes = .getIndicesIfValid(CE);
        this.ShuffleMask = .getShuffleMaskIfValid(CE);
        this.ExplicitTy = .getSourceElementTypeIfValid(CE);
        {
            for (int I = 0; I != CE.Ops.length; ++I) {
                .追加!(Value)(cast(Value[])(Storage), CE.Ops[I]);
            }
        }
        this.Ops = Storage;
    }
    ConstantExpr create(类型_ Ty) {
        switch (this.Opcode) {
            case InstructionKind_.Select: {
                return new SelectConstantExpr(this.Ops[0], this.Ops[1], this.Ops[2]);
            }
            case InstructionKind_.ExtractElement: {
                return new ExtractElementConstantExpr(this.Ops[0], this.Ops[1]);
            }
            case InstructionKind_.InsertElement: {
                return new InsertElementConstantExpr(this.Ops[0], this.Ops[1], this.Ops[2]);
            }
            case InstructionKind_.ShuffleVector: {
                return new ShuffleVectorConstantExpr(this.Ops[0], this.Ops[1], this.ShuffleMask);
            }
            case InstructionKind_.InsertValue: {
                return new InsertValueConstantExpr(this.Ops[0], this.Ops[1], this.Indexes, Ty);
            }
            case InstructionKind_.ExtractValue: {
                return new ExtractValueConstantExpr(this.Ops[0], this.Indexes, Ty);
            }
            case InstructionKind_.GetElementPtr: {
                return GEP_.s·create(this.ExplicitTy, this.Ops[0], this.Ops[1 .. $], Ty, this.SubclassOptionalData);
            }
            case InstructionKind_.ICmp: {
                return new CompareConstantExpr(Ty, InstructionKind_.ICmp, (cast(ubyte)(this.SubclassData)), this.Ops[0], this.Ops[1]);
            }
            case InstructionKind_.FCmp: {
                return new CompareConstantExpr(Ty, InstructionKind_.FCmp, (cast(ubyte)(this.SubclassData)), this.Ops[0], this.Ops[1]);
            }
            default: {
                if (.InstructionKind_isCast(this.Opcode) || (this.Opcode >= InstructionKind_.UnaryOpsBegin && this.Opcode < InstructionKind_.UnaryOpsEnd)) {
                    return new UnaryConstantExpr(this.Opcode, this.Ops[0], Ty);
                }
                if ((this.Opcode >= InstructionKind_.BinaryOpsBegin && this.Opcode < InstructionKind_.BinaryOpsEnd)) {
                    return new BinaryConstantExpr(this.Opcode, this.Ops[0], this.Ops[1], this.SubclassOptionalData);
                }
                assert(false, "Invalid ConstantExpr!"c);
            }
        }
        return 返回零值!(ConstantExpr)();
    }
}
class Module_ {
    this() { }
    static bool s·getSemanticInterposition(Module m) {
        return false;
    }
    static DataLayout s·getDataLayout(Module m) {
        return m.DL;
    }
}
class RetType_ {
    this() { }
    static Align_ s·getRetAlign(CallBase C) {
        if (.函数具有返回值特性(C.特性组, AttrKind_.Alignment)) {
            特性组_ 组 = C.特性组[1];
            int index = AttrKind_.Alignment - AttrKind_.FirstIntAttr;
            return 组.对齐特性[index].值;
        }
        return ··null!(Align_);
    }
    static Align_ s·getRetAlignment(Function F) {
        if (.函数具有返回值特性(F.特性组, AttrKind_.Alignment)) {
            特性组_ 组 = F.特性组[1];
            int index = AttrKind_.Alignment - AttrKind_.FirstIntAttr;
            return 组.对齐特性[index].值;
        }
        return ··null!(Align_);
    }
}
class Argument_ {
    this() { }
    static Align_ s·getParamAlign(Argument A) {
        if ((A.特性组 is ··null!(特性组_)) || A.特性组.对齐特性.length <= 0) {
            return ··null!(Align_);
        }
        int index = AttrKind_.Alignment - AttrKind_.FirstIntAttr;
        对齐特性_ 对齐特性 = A.特性组.对齐特性[index];
        return 对齐特性.值;
    }
    static 类型_ s·hasStructRetAttr(Argument A) {
        if ((A.特性组 is ··null!(特性组_)) || A.特性组.对齐特性.length <= 0) {
            return ··null!(类型_);
        }
        int index = AttrKind_.StructRet - AttrKind_.FirstTypeAttr;
        类型特性_ 类型特性 = A.特性组.类型特性[index];
        return 类型特性.值;
    }
}
class GlobalValue_ {
    this() { }
    static bool s·isDeclaration(GlobalValue G) {
        GlobalVariable GV = .dyn_cast!(GlobalVariable)(G);
        if (GV !is ··null!(GlobalVariable)) {
            return false;
        }
        Function F = .dyn_cast!(Function)(G);
        if ((F !is ··null!(Function)) && (F.符号.标志 & 符号标志_.函数声明_) != 0) {
            return true;
        }
        return false;
    }
    static bool s·isInterposableLinkage(LinkageTypes Linkage) {
        switch (Linkage) {
            case LinkageTypes.WeakAnyLinkage:
            case LinkageTypes.LinkOnceAnyLinkage:
            case LinkageTypes.CommonLinkage:
            case LinkageTypes.ExternalWeakLinkage: {
                return true;
            }
            case LinkageTypes.AvailableExternallyLinkage:
            case LinkageTypes.LinkOnceODRLinkage:
            case LinkageTypes.WeakODRLinkage:
            // The above three cannot be overridden but can be de-refined.
            case LinkageTypes.ExternalLinkage:
            case LinkageTypes.AppendingLinkage:
            case LinkageTypes.InternalLinkage:
            case LinkageTypes.PrivateLinkage: {
                return false;
            }
            default: break;
        }
        assert(false, "Fully covered 假如 above!"c);
        return false;
    }
    static bool s·isWeakForLinker(LinkageTypes Linkage) {
        return Linkage == LinkageTypes.WeakAnyLinkage || Linkage == LinkageTypes.WeakODRLinkage || Linkage == LinkageTypes.LinkOnceAnyLinkage || Linkage == LinkageTypes.LinkOnceODRLinkage || Linkage == LinkageTypes.CommonLinkage || Linkage == LinkageTypes.ExternalWeakLinkage;
    }
    static bool s·isWeakForLinker(GlobalValue G) {
        return GlobalValue_.s·isWeakForLinker(G.Linkage);
    }
    static bool s·isAvailableExternallyLinkage(LinkageTypes Linkage) {
        return Linkage == LinkageTypes.AvailableExternallyLinkage;
    }
    static bool s·isDeclarationForLinker(GlobalValue G) {
        if (GlobalValue_.s·hasAvailableExternallyLinkage(G)) {
            return true;
        }
        return GlobalValue_.s·isDeclaration(G);
    }
    static bool s·isStrongDefinitionForLinker(GlobalValue G) {
        return !(GlobalValue_.s·isDeclarationForLinker(G) || GlobalValue_.s·isWeakForLinker(G));
    }
    static bool s·hasAvailableExternallyLinkage(GlobalValue G) {
        return GlobalValue_.s·isAvailableExternallyLinkage(G.Linkage);
    }
    static bool s·isDSOLocal(GlobalValue V) {
        return V.IsDSOLocal;
    }
    static bool s·isInterposable(GlobalValue V) {
        if (GlobalValue_.s·isInterposableLinkage(V.Linkage)) {
            return true;
        }
        return !GlobalValue_.s·isDSOLocal(V);
    }
    static bool s·hasGlobalUnnamedAddr(GlobalValue V) {
        return V.UnnamedAddrVal == UnnamedAddr.Global;
    }
    static CmpInst_Predicate_ s·areGlobalsPotentiallyEqual(GlobalValue GV1, GlobalValue GV2) {
        bool delegate(GlobalValue) isGlobalUnsafeForEquality;
        bool isGlobalUnsafeForEquality·func(GlobalValue V) {
            GlobalVariable GVar;
            if (GlobalValue_.s·isInterposable(V) || GlobalValue_.s·hasGlobalUnnamedAddr(V)) {
                return true;
            }
            GVar = .dyn_cast!(GlobalVariable)(V);
            if (GVar !is ··null!(GlobalVariable)) {
                类型_ Ty = .获取符号的类型(GVar.符号);
                if (!TY_.s·isSized(Ty)) {
                    return true;
                }
                if (TY_.s·isEmptyTy(Ty)) {
                    return true;
                }
            }
            return false;
        }
        isGlobalUnsafeForEquality = &isGlobalUnsafeForEquality·func;
        if (!.isGlobalAlias(GV1) && !.isGlobalAlias(GV2)) {
            if (!isGlobalUnsafeForEquality(GV1) && !isGlobalUnsafeForEquality(GV2)) {
                return CmpInst_Predicate_.ICMP_NE;
            }
        }
        return CmpInst_Predicate_.BAD_ICMP_PREDICATE;
    }
    static ulong s·getAlignment(GlobalValue GV) {
        Align_ al = GV.Align;
        return al ? al.value() : 0;
    }
}
class StructLayout {
    ulong StructSize;
    Align_ StructAlignment;
    uint IsPadded;
    uint NumElements;
    ulong[] MemberOffsets;
    this() { }
    this(结构类型_ STy, DataLayout DL) {
        assert(!ST_.s·isOpaque(STy), "Cannot get layout of opaque structs"c);
        this.StructSize = 0;
        this.IsPadded = 0;
        this.NumElements = ST_.s·getNumElements(STy);
        this.MemberOffsets = 创建数组!(ulong)();
        this.MemberOffsets.length = this.NumElements;
        this.StructAlignment = new Align_(1);
        {
            // Loop over each of the elements, placing them in memory.
            for (int i = 0; i < this.NumElements; ++i) {
                类型_ Ty = ST_.s·getElementType(STy, i);
                Align_ TyAlign = ST_.s·isPacked(STy) ? new Align_(1) : DataLayout_.s·getABITypeAlign(DL, Ty);
                // Add padding if necessary to align the data element properly.
                if (!isAligned(TyAlign, this.StructSize)) {
                    this.IsPadded = 1;
                    this.StructSize = alignTo(this.StructSize, TyAlign);
                }
                // Keep track of maximum alignment constraint.
                this.StructAlignment = TyAlign.ShiftValue > this.StructAlignment.ShiftValue ? TyAlign : this.StructAlignment;
                this.MemberOffsets[i] = this.StructSize;
                // Consume space for this data item
                this.StructSize += DataLayout_.s·getTypeAllocSize(DL, Ty);
            }
        }
        // Add padding to the end of the struct so that it could be put in an array
        // and all array elements would be aligned correctly.
        if (!isAligned(this.StructAlignment, this.StructSize)) {
            this.IsPadded = 1;
            this.StructSize = alignTo(this.StructSize, this.StructAlignment);
        }
    }
    Align_ getAlignment() {
        return this.StructAlignment;
    }
    ulong getSizeInBytes() { return this.StructSize; }
    ulong getSizeInBits() { return 8 * this.StructSize; }
    static StructLayout s·getStructLayout(DataLayout DL, 结构类型_ STy) {
        dstring Id = .获取类型文本Id(STy);
        if (LayoutMap.具有(Id)) {
            return LayoutMap.获取(Id);
        }
        StructLayout L = new StructLayout(STy, DL);
        LayoutMap.p·设置(Id, L);
        return LayoutMap.获取(Id);
    }
}
class DataLayout_ {
    this() { }
    static Align_ s·getAlignment(DataLayout DL, 类型_ Ty, bool abi_or_pref = false) {
        assert(TY_.s·isSized(Ty), "Cannot getTypeInfo() on a type that is unsized!"c);
        switch (Ty.种类) {
            // Early escape for the non-numeric types.
            case TypeID_.LabelTyID: {
                return abi_or_pref ? DL.getPointerABIAlignment(0) : DL.getPointerPrefAlignment(0);
            }
            case TypeID_.PointerTyID: {
                uint AS = .cast_!(指针类型_)(Ty).地址;
                return abi_or_pref ? DL.getPointerABIAlignment(AS) : DL.getPointerPrefAlignment(AS);
            }
            case TypeID_.ArrayTyID: {
                return DataLayout_.s·getAlignment(DL, .cast_!(数组类型_)(Ty).元素类型, abi_or_pref);
            }
            case TypeID_.StructTyID: {
                // Packed structure types always have an ABI alignment of one.
                if (.cast_!(结构类型_)(Ty).是压缩的 && abi_or_pref) {
                    return new Align_(1);
                }
                // Get the layout annotation... which is lazily created on demand.
                StructLayout Layout = StructLayout.s·getStructLayout(DL, .cast_!(结构类型_)(Ty));
                LayoutAlignElem AggregateAlign = DL.Alignments[0];
                assert(AggregateAlign.AlignType == AlignTypeEnum.AGGREGATE_ALIGN, "Aggregate alignment must be first alignment entry"c);
                Align_ Align = abi_or_pref ? AggregateAlign.ABIAlign : AggregateAlign.PrefAlign;
                if (Align.ShiftValue >= Layout.getAlignment().ShiftValue) {
                    return Align;
                }
                return Layout.getAlignment();
            }
            case TypeID_.IntegerTyID: {
                return DL.getIntegerAlignment(.cast_!(整数类型_)(Ty).位数, abi_or_pref);
            }
            case TypeID_.HalfTyID:
            case TypeID_.BFloatTyID:
            case TypeID_.FloatTyID:
            case TypeID_.DoubleTyID:
            // PPC_FP128TyID and FP128TyID have different data contents, but the
            // same size and alignment, so they look the same here.
            case TypeID_.PPC_FP128TyID:
            case TypeID_.FP128TyID:
            case TypeID_.X86_FP80TyID: {
                uint BitWidth = (cast(uint)(DataLayout_.s·getTypeSizeInBits(DL, Ty).getFixedSize()));
                LayoutAlignElem I = DL.findAlignmentLowerBound(AlignTypeEnum.FLOAT_ALIGN, BitWidth);
                if ((I !is ··null!(LayoutAlignElem)) && I.AlignType == AlignTypeEnum.FLOAT_ALIGN && I.TypeBitWidth == BitWidth) {
                    return abi_or_pref ? I.ABIAlign : I.PrefAlign;
                }
                // If we still couldn't find a reasonable 默认 alignment, fall back
                // to a simple heuristic that the alignment is the first power of two
                // greater-or-equal to the store size of the type.  This is a reasonable
                // approximation of reality, and 如果 the user wanted something less
                // less conservative, they should have specified it explicitly in the data
                // layout.
                return new Align_(PowerOf2Ceil(BitWidth / 8));
            }
            case TypeID_.X86_MMXTyID:
            case TypeID_.FixedVectorTyID:
            case TypeID_.ScalableVectorTyID: {
                ulong BitWidth = DataLayout_.s·getTypeSizeInBits(DL, Ty).getKnownMinSize();
                LayoutAlignElem I = DL.findAlignmentLowerBound(AlignTypeEnum.VECTOR_ALIGN, (cast(uint)(BitWidth)));
                if ((I !is ··null!(LayoutAlignElem)) && I.AlignType == AlignTypeEnum.VECTOR_ALIGN && I.TypeBitWidth == BitWidth) {
                    return abi_or_pref ? I.ABIAlign : I.PrefAlign;
                }
                // By 默认, use natural alignment for vector types. This is consistent
                // with what clang and llvm-gcc do.
                //
                // We're only calculating a natural alignment, so it doesn't have to be
                // based on the full size for scalable vectors. Using the minimum element
                // count should be enough here.
                return new Align_(PowerOf2Ceil(DataLayout_.s·getTypeStoreSize(DL, Ty).getKnownMinSize()));
            }
            case TypeID_.X86_AMXTyID: {
                return new Align_(64);
            }
            default: {
                assert(false, "Bad type for getAlignment!!!"c);
            }
        }
        return new Align_(1);
    }
    static Align_ s·getABITypeAlign(DataLayout DL, 类型_ Ty) {
        return DataLayout_.s·getAlignment(DL, Ty, true);
    }
    static Align_ s·getPrefTypeAlign(DataLayout DL, 类型_ Ty) {
        return DataLayout_.s·getAlignment(DL, Ty, false);
    }
    static ulong s·getABITypeAlignment(DataLayout DL, 类型_ Ty) {
        return DataLayout_.s·getABITypeAlign(DL, Ty).value();
    }
    static ulong s·getPrefTypeAlignment(DataLayout DL, 类型_ Ty) {
        return DataLayout_.s·getPrefTypeAlign(DL, Ty).value();
    }
    static TypeSize s·getTypeStoreSize(DataLayout DL, 类型_ Ty) {
        TypeSize BaseSize = DataLayout_.s·getTypeSizeInBits(DL, Ty);
        return new TypeSize((BaseSize.getKnownMinSize() + 7) / 8, BaseSize.isScalable());
    }
    static ulong s·getTypeAllocSize(DataLayout DL, 类型_ Ty) {
        return alignTo_1(DataLayout_.s·getTypeStoreSize(DL, Ty).getValue(), DataLayout_.s·getABITypeAlignment(DL, Ty));
    }
    static ulong s·getTypeAllocSizeInBits(DataLayout DL, 类型_ Ty) {
        return 8 * DataLayout_.s·getTypeAllocSize(DL, Ty);
    }
    static TypeSize s·getTypeSizeInBits(DataLayout DL, 类型_ Ty) {
        assert(TY_.s·isSized(Ty), "Cannot getTypeInfo() on a type that is unsized!"c);
        switch (Ty.种类) {
            case TypeID_.LabelTyID: {
                return Fixed(DL.getPointerSizeInBits(0));
            }
            case TypeID_.PointerTyID: {
                return Fixed(DL.getPointerSizeInBits(.cast_!(指针类型_)(Ty).地址));
            }
            case TypeID_.ArrayTyID: {
                数组类型_ ATy = .cast_!(数组类型_)(Ty);
                return new TypeSize(ATy.数量 * DataLayout_.s·getTypeAllocSizeInBits(DL, ATy.元素类型), false);
            }
            case TypeID_.StructTyID: {
                // Get the layout annotation... which is lazily created on demand.
                return Fixed(StructLayout.s·getStructLayout(DL, .cast_!(结构类型_)(Ty)).getSizeInBits());
            }
            case TypeID_.IntegerTyID: {
                return Fixed(.cast_!(整数类型_)(Ty).位数);
            }
            case TypeID_.HalfTyID:
            case TypeID_.BFloatTyID: {
                return Fixed(16);
            }
            case TypeID_.FloatTyID: {
                return Fixed(32);
            }
            case TypeID_.DoubleTyID:
            case TypeID_.X86_MMXTyID: {
                return Fixed(64);
            }
            case TypeID_.PPC_FP128TyID:
            case TypeID_.FP128TyID: {
                return Fixed(128);
            }
            case TypeID_.X86_AMXTyID: {
                return Fixed(8192);
            }
            // In memory objects this is always aligned to a higher boundary, but
            // only 80 bits contain information.
            case TypeID_.X86_FP80TyID: {
                return Fixed(80);
            }
            case TypeID_.FixedVectorTyID:
            case TypeID_.ScalableVectorTyID: {
                向量类型_ VTy = .cast_!(向量类型_)(Ty);
                ElementCount EltCnt = VTy_.s·getElementCount(VTy);
                ulong MinBits = EltCnt.getKnownMinValue() * DataLayout_.s·getTypeSizeInBits(DL, VTy.元素类型).getFixedSize();
                return new TypeSize(MinBits, EltCnt.isScalable());
            }
            default: {
                assert(false, "DataLayout.getTypeSizeInBits(): Unsupported type"c);
                return new TypeSize();
            }
        }
    }
    static Align_ s·getPreferredAlign(DataLayout DL, GlobalVariable GV) {
        Align_ GVAlignment = GV.Align;
        if ((GVAlignment !is ··null!(Align_)) && (GV.Section !is ··null!(dstring))) {
            return GVAlignment;
        }
        类型_ ElemType = GV.类型;
        Align_ Alignment = DataLayout_.s·getPrefTypeAlign(DL, ElemType);
        if (GVAlignment !is ··null!(Align_)) {
            if (GVAlignment.Op大于等于(Alignment)) {
                Alignment = GVAlignment;
            }
            else {
                Alignment = GVAlignment.Op大于等于(DataLayout_.s·getABITypeAlign(DL, ElemType)) ? GVAlignment : DataLayout_.s·getABITypeAlign(DL, ElemType);
            }
        }
        if ((GV.Ops !is ··null!(Value[])) && (GV.Ops[0] !is ··null!(Value)) && (GVAlignment is ··null!(Align_))) {
            if (Alignment.Op小于(new Align_(16))) {
                if (DataLayout_.s·getTypeSizeInBits(DL, ElemType).Op值() > 128) {
                    Alignment = new Align_(16);
                }
            }
        }
        return Alignment;
    }
    static 整数类型_ s·getIntPtrType(DataLayout DL, uint AddressSpace) {
        return TGet_.s·IntTy_get(DL.getPointerSizeInBits(AddressSpace));
    }
    static 类型_ s·getIntPtrType(DataLayout DL, 类型_ Ty) {
        assert(.isPtrOrPtrVectorTy(Ty), "Expected a pointer or pointer vector type."c);
        uint NumBits = DataLayout_.s·getPointerTypeSizeInBits(DL, Ty);
        整数类型_ IntTy = TGet_.s·IntTy_get(NumBits);
        向量类型_ VecTy = .dyn_cast!(向量类型_)(Ty);
        if (VecTy !is ··null!(向量类型_)) {
            return TGet_.s·VTy_get(IntTy, VTy_.s·getElementCount(VecTy));
        }
        return IntTy;
    }
    static uint s·getPointerTypeSizeInBits(DataLayout DL, 类型_ Ty) {
        assert(.isPtrOrPtrVectorTy(Ty), "This should only be called with a pointer or pointer vector type"c);
        Ty = .getScalarType(Ty);
        return DL.getPointerSizeInBits((cast(指针类型_)(Ty)).地址);
    }
    static uint s·getProgramAddressSpace(DataLayout DL) {
        return DL.ProgramAddrSpace;
    }
}
class DuplicateInfoForSymbol {
    基础节点.节点_[] firstFileLocations;
    基础节点.节点_[] secondFileLocations;
    bool isBlockScoped;
    this() { }
    this(基础节点.节点_[] firstFileLocations, 基础节点.节点_[] secondFileLocations, bool isBlockScoped) {
        this.firstFileLocations = firstFileLocations;
        this.secondFileLocations = secondFileLocations;
        this.isBlockScoped = isBlockScoped;
    }
}
class DuplicateInfoForFiles {
    基础节点.源文件_ firstFile;
    基础节点.源文件_ secondFile;
    词典_!(DuplicateInfoForSymbol) conflictingSymbols;
    this() { }
    this(基础节点.源文件_ firstFile, 基础节点.源文件_ secondFile, 词典_!(DuplicateInfoForSymbol) conflictingSymbols) {
        this.firstFile = firstFile;
        this.secondFile = secondFile;
        this.conflictingSymbols = conflictingSymbols;
    }
}
class Match_ {
    this() { }
    bool match(Value V) {
        return false;
    }
}
class apint_match_ : Match_ {
    APInt_* Res;
    bool AllowUndef;
    this() { }
    this(APInt_* Res, bool AllowUndef = false) {
        this.Res = Res;
        this.AllowUndef = AllowUndef;
    }
    override bool match(Value V) {
        ConstantInt CI = .dyn_cast!(ConstantInt)(V);
        if (CI !is ··null!(ConstantInt)) {
            this.Res = &CI.Val;
            return true;
        }
        if (.isVectorType(V.类型)) {
            Constant C = .dyn_cast!(Constant)(V);
            if (C !is ··null!(Constant)) {
                ConstantInt CI2 = .dyn_cast_or_null!(ConstantInt)(.getSplatValue(C, this.AllowUndef));
                if (CI2 !is ··null!(ConstantInt)) {
                    this.Res = &CI2.Val;
                    return true;
                }
            }
        }
        return false;
    }
}
class undef_match : Match_ {
    this() { }
    override bool match(Value V) {
        return this._check(V);
    }
    private bool _check(Value V) {
        bool delegate(ConstantAggregate) CheckValue;
        ConstantAggregate CA;
        词典_!(ConstantAggregate) Seen;
        词典_!(ConstantAggregate) Worklist;
        bool CheckValue·func(ConstantAggregate CA) {
            foreach (Value Op; CA.Ops) {
                if (.isUndefValue(Op)) {
                    return true;
                }
                ConstantAggregate CA2 = .dyn_cast!(ConstantAggregate)(Op);
                if (CA2 is ··null!(ConstantAggregate)) {
                    return false;
                }
                dstring 键 = ·to!(dstring)(CA2.toHash());
                if (Seen.具有(键)) {
                    continue;
                }
                else {
                    Seen.p·设置(键, CA2);
                    Worklist.p·设置(键, CA2);
                }
            }
            return true;
        }
        CheckValue = &CheckValue·func;
        if (.isUndefValue(V)) {
            return true;
        }
        CA = .dyn_cast!(ConstantAggregate)(V);
        if (CA is ··null!(ConstantAggregate)) {
            return false;
        }
        Seen = new 词典_!(ConstantAggregate)();
        Worklist = new 词典_!(ConstantAggregate)();
        if (!CheckValue(CA)) {
            return false;
        }
        while(Worklist.大小() > 0) {
            const(dstring[]) 键组 = Worklist.键组();
            dstring k = 键组[0];
            ConstantAggregate v = Worklist.获取(k);
            if (!CheckValue(v)) {
                return false;
            }
            Worklist.删除值(k);
        }
        return true;
    }
}
class isValue_ {
    this() { }
    bool isValue(Value V) {
        return false;
    }
}
class is_zero_int_ : isValue_ {
    this() { }
    override bool isValue(Value V) {
        if (V is ··null!(Value)) {
            return false;
        }
        ConstantInt IV = .dyn_cast!(ConstantInt)(V);
        if (IV is ··null!(ConstantInt)) {
            return false;
        }
        return IV.Val.isZero();
    }
}
class is_one : isValue_ {
    this() { }
    override bool isValue(Value V) {
        if (V is ··null!(Value)) {
            return false;
        }
        ConstantInt IV = .dyn_cast!(ConstantInt)(V);
        if (IV is ··null!(ConstantInt)) {
            return false;
        }
        return IV.Val.isOne();
    }
}
class is_neg_zero_fp : isValue_ {
    this() { }
    override bool isValue(Value V) {
        if (V is ··null!(Value)) {
            return false;
        }
        ConstantFP IV = .dyn_cast!(ConstantFP)(V);
        if (IV is ··null!(ConstantFP)) {
            return false;
        }
        return IV.Val.isNegZero();
    }
}
class cst_pred_ty(T, ConstantVal) : Match_ {
    T V;
    this() { }
    this(T v) {
        this.V = v;
    }
    override bool match(Value VV) {
        Constant CV = .dyn_cast!(ConstantVal)(VV);
        if (CV !is ··null!(Constant)) {
            return this.V.isValue(CV);
        }
        if (.isVectorType(VV.类型)) {
            向量类型_ VTy = .dyn_cast!(向量类型_)(VV.类型);
            Constant C = .dyn_cast!(Constant)(VV);
            if (C !is ··null!(Constant)) {
                ConstantVal CV2 = .dyn_cast_or_null!(ConstantVal)(.getSplatValue(C, false));
                if (CV2 !is ··null!(ConstantVal)) {
                    return this.V.isValue(CV2);
                }
            }
            if (!.isFixedVectorType(VTy)) {
                return false;
            }
            uint NumElts = VTy.数量;
            bool HasNonUndefElements = false;
            {
                for (int i = 0; i < NumElts; ++i) {
                    Constant Elt = .getAggregateElement(C, i);
                    if (Elt is ··null!(Constant)) {
                        return false;
                    }
                    if (.isUndefValue(Elt)) {
                        continue;
                    }
                    Constant CV3 = .dyn_cast!(ConstantVal)(Elt);
                    if ((CV3 is ··null!(Constant)) || !this.V.isValue(CV3)) {
                        return false;
                    }
                    HasNonUndefElements = true;
                }
            }
            return HasNonUndefElements;
        }
        return false;
    }
}
class is_zero : Match_ {
    this() { }
    override bool match(Value V) {
        Constant C = .dyn_cast!(Constant)(V);
        return (C !is ··null!(Constant)) && (.isNullValue(C) || (new cst_pred_ty!(is_zero_int_, ConstantInt)(new is_zero_int_())).match(V));
    }
}
class match_combine_or : Match_ {
    Match_ L;
    Match_ R;
    this() { }
    this(Match_ l, Match_ r) {
        this.L = l;
        this.R = r;
    }
    override bool match(Value V) {
        return this.L.match(V) || this.R.match(V);
    }
}
class InstC_ {
    this() { }
    static RetInst s·Ret_C(Value V = ··null!(Value)) {
        return new RetInst(.VoidTy, V);
    }
    static BranchInst s·Branch_C(BasicBlock IfTrue, BasicBlock IfFalse = ··null!(BasicBlock), Value Cond = ··null!(Value)) {
        return new BranchInst(.VoidTy, IfTrue, IfFalse, Cond);
    }
    static SwitchInst s·Switch_C(Value Cond, BasicBlock DefaultBB, 跳转表_[] Table) {
        return new SwitchInst(.VoidTy, Cond, DefaultBB, Table);
    }
    static IndirectBrInst s·IndirectBr_C(Value Address, BasicBlock[] DestList) {
        return new IndirectBrInst(.VoidTy, Address, DestList);
    }
    static InvokeInst s·Invoke_C(函数类型_ FTy, Value Fn, BasicBlock IfNormal, BasicBlock IfException, Value[] Args, BundleDef[] Bundles, 特性组_[] 特性组, CallingConv_ CC) {
        Align_ 对齐 = new Align_();
        if (.函数具有返回值特性(特性组, AttrKind_.Alignment)) {
            特性组_ 组 = 特性组[1];
            int index = AttrKind_.Alignment - AttrKind_.FirstIntAttr;
            对齐 = 组.对齐特性[index].值;
        }
        return new InvokeInst(FTy, Fn, IfNormal, IfException, Args, Bundles, 特性组, 对齐, CC);
    }
    static ResumeInst s·Resume_C(Value V = ··null!(Value)) {
        return new ResumeInst(V);
    }
    static CleanupReturnInst s·CleanupRet_C(Value CleanupPad, BasicBlock UnwindBB = ··null!(BasicBlock)) {
        return new CleanupReturnInst(.VoidTy, CleanupPad, UnwindBB);
    }
    static CleanupPadInst s·CleanupPad_C(Value ParentPad, Value[] Args) {
        return new CleanupPadInst(ParentPad, Args);
    }
    static CatchPadInst s·CatchPad_C(Value CatchSwitch, Value[] Args) {
        return new CatchPadInst(CatchSwitch, Args);
    }
    static CatchReturnInst s·CatchRet_C(Value CatchPad, BasicBlock BB) {
        return new CatchReturnInst(.VoidTy, CatchPad, BB);
    }
    static CatchSwitchInst s·CatchSwitch_C(Value ParentPad, BasicBlock[] Table, BasicBlock UnwindDest = ··null!(BasicBlock)) {
        return new CatchSwitchInst(.VoidTy, ParentPad, Table, UnwindDest);
    }
    static CallBrInst s·CallBr_C(函数类型_ FTy, Value Fn, BasicBlock DefaultDest, BasicBlock[] IndirectDests, Value[] Args, BundleDef[] Bundles, 特性组_[] 特性组, CallingConv_ CC) {
        Align_ 对齐 = new Align_();
        if (.函数具有返回值特性(特性组, AttrKind_.Alignment)) {
            特性组_ 组 = 特性组[1];
            int index = AttrKind_.Alignment - AttrKind_.FirstIntAttr;
            对齐 = 组.对齐特性[index].值;
        }
        return new CallBrInst(FTy, Fn, DefaultDest, IndirectDests, Args, Bundles, 特性组, 对齐, CC);
    }
    static AllocaInst s·Alloca_C(类型_ Ty, uint AddrSpace, Value Size, Align_ 对齐, bool IsInAlloca, bool IsSwiftError) {
        AllocaInst I = new AllocaInst();
        I.类型 = TGet_.s·PtrTy_get(Ty, AddrSpace);
        I.AllocatedType = Ty;
        I.对齐 = 对齐;
        I.Ops.length = 1;
        I.Ops[0] = Size;
        I.IsInAlloca = IsInAlloca;
        I.IsSwiftError = IsSwiftError;
        return I;
    }
    static LoadInst s·Load_C(类型_ Ty, Value Val, bool isVolatile, Align_ 对齐, AtomicOrdering_ 排序, ubyte SSID) {
        LoadInst I = new LoadInst();
        I.类型 = Ty;
        I.对齐 = 对齐;
        I.Ops.length = 1;
        I.Ops[0] = Val;
        I.isVolatile = isVolatile;
        I.OrderingField = 排序;
        I.SSID = SSID;
        return I;
    }
    static LoadInst s·Store_C(类型_ Ty, Value Val, Value Ptr, bool isVolatile, Align_ 对齐, AtomicOrdering_ 排序, ubyte SSID) {
        LoadInst I = new LoadInst();
        I.类型 = Ty;
        I.对齐 = 对齐;
        I.Ops.length = 2;
        I.Ops[0] = Val;
        I.Ops[1] = Ptr;
        I.isVolatile = isVolatile;
        I.OrderingField = 排序;
        I.SSID = SSID;
        return I;
    }
    static UnaryOperator s·Unary_C(InstructionKind_ Opc, Value Op, FastMathFlags_ FMF = FastMathFlags_.无效值_) {
        switch (Opc) {
            case InstructionKind_.FNeg: {
                return new FNegInst(Op, FMF);
            }
            default: break;
        }
        assert(false, "不可及"c);
        return 返回零值!(UnaryOperator)();
    }
    static Instruction s·Cast_C(InstructionKind_ Opc, Value OP, 类型_ Ty) {
        switch (Opc) {
            case InstructionKind_.Trunc: {
                return new TruncInst(Ty, OP);
            }
            case InstructionKind_.ZExt: {
                return new ZExtInst(Ty, OP);
            }
            case InstructionKind_.SExt: {
                return new SExtInst(Ty, OP);
            }
            case InstructionKind_.FPTrunc: {
                return new FPTruncInst(Ty, OP);
            }
            case InstructionKind_.FPExt: {
                return new FPExtInst(Ty, OP);
            }
            case InstructionKind_.BitCast: {
                return new BitCastInst(Ty, OP);
            }
            case InstructionKind_.AddrSpaceCast: {
                return new AddrSpaceCastInst(Ty, OP);
            }
            case InstructionKind_.UIToFP: {
                return new UIToFPInst(Ty, OP);
            }
            case InstructionKind_.SIToFP: {
                return new SIToFPInst(Ty, OP);
            }
            case InstructionKind_.FPToUI: {
                return new FPToUIInst(Ty, OP);
            }
            case InstructionKind_.FPToSI: {
                return new FPToSIInst(Ty, OP);
            }
            case InstructionKind_.IntToPtr: {
                return new IntToPtrInst(Ty, OP);
            }
            case InstructionKind_.PtrToInt: {
                return new PtrToIntInst(Ty, OP);
            }
            default: break;
        }
        assert(false, "不可及"c);
        return 返回零值!(Instruction)();
    }
    static BinaryOperator s·Binary_C(InstructionKind_ Opc, Value LHS, Value RHS, FastMathFlags_ FMF = FastMathFlags_.无效值_, bool Exact = false) {
        switch (Opc) {
            case InstructionKind_.Add: {
                AddInst I = new AddInst(LHS, RHS);
                I.FMF = FMF;
                I.Exact = Exact;
                return I;
            }
            case InstructionKind_.FAdd: {
                FAddInst I = new FAddInst(LHS, RHS);
                I.FMF = FMF;
                I.Exact = Exact;
                return I;
            }
            case InstructionKind_.Sub: {
                SubInst I = new SubInst(LHS, RHS);
                I.FMF = FMF;
                I.Exact = Exact;
                return I;
            }
            case InstructionKind_.FSub: {
                FSubInst I = new FSubInst(LHS, RHS);
                I.FMF = FMF;
                I.Exact = Exact;
                return I;
            }
            case InstructionKind_.Mul: {
                MulInst I = new MulInst(LHS, RHS);
                I.FMF = FMF;
                I.Exact = Exact;
                return I;
            }
            case InstructionKind_.FMul: {
                FMulInst I = new FMulInst(LHS, RHS);
                I.FMF = FMF;
                I.Exact = Exact;
                return I;
            }
            case InstructionKind_.UDiv: {
                UDivInst I = new UDivInst(LHS, RHS);
                I.FMF = FMF;
                I.Exact = Exact;
                return I;
            }
            case InstructionKind_.SDiv: {
                SDivInst I = new SDivInst(LHS, RHS);
                I.FMF = FMF;
                I.Exact = Exact;
                return I;
            }
            case InstructionKind_.FDiv: {
                FDivInst I = new FDivInst(LHS, RHS);
                I.FMF = FMF;
                I.Exact = Exact;
                return I;
            }
            case InstructionKind_.URem: {
                URemInst I = new URemInst(LHS, RHS);
                I.FMF = FMF;
                I.Exact = Exact;
                return I;
            }
            case InstructionKind_.SRem: {
                SRemInst I = new SRemInst(LHS, RHS);
                I.FMF = FMF;
                I.Exact = Exact;
                return I;
            }
            case InstructionKind_.FRem: {
                FRemInst I = new FRemInst(LHS, RHS);
                I.FMF = FMF;
                I.Exact = Exact;
                return I;
            }
            case InstructionKind_.Shl: {
                ShlInst I = new ShlInst(LHS, RHS);
                I.FMF = FMF;
                I.Exact = Exact;
                return I;
            }
            case InstructionKind_.LShr: {
                LShrInst I = new LShrInst(LHS, RHS);
                I.FMF = FMF;
                I.Exact = Exact;
                return I;
            }
            case InstructionKind_.AShr: {
                AShrInst I = new AShrInst(LHS, RHS);
                I.FMF = FMF;
                I.Exact = Exact;
                return I;
            }
            case InstructionKind_.And: {
                AndInst I = new AndInst(LHS, RHS);
                I.FMF = FMF;
                I.Exact = Exact;
                return I;
            }
            case InstructionKind_.Or: {
                OrInst I = new OrInst(LHS, RHS);
                I.FMF = FMF;
                I.Exact = Exact;
                return I;
            }
            case InstructionKind_.Xor: {
                XorInst I = new XorInst(LHS, RHS);
                I.FMF = FMF;
                I.Exact = Exact;
                return I;
            }
            default: break;
        }
        assert(false, "不可及"c);
        return 返回零值!(BinaryOperator)();
    }
    static CmpInst s·Cmp_C(InstructionKind_ Opc, CmpInst_Predicate_ pred, Value LHS, Value RHS, FastMathFlags_ FMF = FastMathFlags_.无效值_) {
        类型_ Ty = .makeCmpResultType(LHS.类型);
        if (Opc == InstructionKind_.ICmp) {
            return new ICmpInst(Ty, pred, LHS, RHS, FMF);
        }
        else if (Opc == InstructionKind_.FCmp) {
            return new FCmpInst(Ty, pred, LHS, RHS, FMF);
        }
        assert(false, "不可及"c);
        return 返回零值!(CmpInst)();
    }
    static VAArgInst s·VAArg_C(类型_ Ty, Value List) {
        return new VAArgInst(Ty, List);
    }
    static ExtractElementInst s·ExtractElement_C(Value Val, Value Index) {
        类型_ Ty = .cast_!(向量类型_)(Val.类型).元素类型;
        return new ExtractElementInst(Ty, Val, Index);
    }
    static InsertElementInst s·InsertElement_C(Value Val, Value Elt, Value Index) {
        return new InsertElementInst(Val.类型, Val, Elt, Index);
    }
    static ShuffleVectorInst s·ShuffleVector_C(Value V1, Value V2, Constant Mask) {
        ShuffleVectorInst I = new ShuffleVectorInst();
        向量类型_ Ty = TGet_.s·VTy_get(.cast_!(向量类型_)(V1.类型).元素类型, VTy_.s·getElementCount(.cast_!(向量类型_)(Mask.类型)));
        I.类型 = Ty;
        I.Ops[0] = V1;
        I.Ops[1] = V2;
        int[] MaskArr = SVI_.s·getShuffleMask(Mask);
        I.ShuffleMask = MaskArr;
        I.ShuffleMaskForBitcode = SVI_.s·convertShuffleMaskForBitcode(MaskArr, Ty);
        return I;
    }
    static PHINode s·PHINode_C(类型_ Ty, Value[] PHIVals, FastMathFlags_ FMF) {
        PHINode I = new PHINode();
        I.类型 = Ty;
        {
            for (int i = 0; i < PHIVals.length; i += 2) {
                .追加!(Value)(I.Ops, PHIVals[i]);
            }
        }
        {
            for (int i = 1; i < PHIVals.length; i += 2) {
                .追加!(Value)(I.Ops, PHIVals[i]);
            }
        }
        I.FMF = FMF;
        return I;
    }
    static LandingPadInst s·LandingPad_C(类型_ Ty, bool Cleanup, Constant[] CVS) {
        LandingPadInst I = new LandingPadInst();
        I.类型 = Ty;
        .追加!(Value)(I.Ops, cast(Value[])(CVS));
        I.Cleanup = Cleanup;
        return I;
    }
    static FreezeInst s·Freeze_C(Value Op) {
        return new FreezeInst(Op);
    }
    static CallInst s·Call_C(函数类型_ FTy, Value Fn, Value[] Args, BundleDef[] Bundles, 特性组_[] 特性组, CallingConv_ CC, FastMathFlags_ FMF, TailCallKind_ TCK) {
        Align_ 对齐 = new Align_();
        if (.函数具有返回值特性(特性组, AttrKind_.Alignment)) {
            特性组_ 组 = 特性组[1];
            int index = AttrKind_.Alignment - AttrKind_.FirstIntAttr;
            对齐 = 组.对齐特性[index].值;
        }
        return new CallInst(FTy, Fn, Args, Bundles, 特性组, 对齐, CC, FMF, TCK);
    }
    static AtomicCmpXchgInst s·AtomicCmpXchg_C(Value Ptr, Value Cmp, Value NewVal, Align_ Alignment, AtomicOrdering_ SuccessOrdering, AtomicOrdering_ FailureOrdering, ubyte SSID, bool isVolatile, bool isWeak) {
        AtomicCmpXchgInst I = new AtomicCmpXchgInst();
        I.类型 = TGet_.s·STy_get([Cmp.类型, .Int1Ty]);
        I.Ops.length = 3;
        I.Ops[0] = Ptr;
        I.Ops[1] = Cmp;
        I.Ops[2] = NewVal;
        I.对齐 = Alignment;
        I.SuccessOrdering = SuccessOrdering;
        I.FailureOrdering = FailureOrdering;
        I.SSID = SSID;
        I.isVolatile = isVolatile;
        I.isWeak = isWeak;
        return I;
    }
    static AtomicRMWInst s·AtomicRMW_C(AtomicRMWInstBinOp_ BinOp, Value Ptr, Value Val, Align_ Alignment, AtomicOrdering_ Ordering, ubyte SSID, bool isVolatile) {
        AtomicRMWInst I = new AtomicRMWInst();
        I.类型 = Val.类型;
        I.Ops.length = 2;
        I.Ops[0] = Ptr;
        I.Ops[1] = Val;
        I.对齐 = Alignment;
        I.SSID = SSID;
        I.isVolatile = isVolatile;
        I.Ordering = Ordering;
        return I;
    }
    static FenceInst s·Fence_C(AtomicOrdering_ Ordering, ubyte SSID) {
        FenceInst I = new FenceInst();
        I.类型 = .VoidTy;
        I.Ordering = Ordering;
        I.SSID = SSID;
        return I;
    }
    static GetElementPtrInst s·GetElementPtr_C(Value Ptr, Value[] Indices, bool InBounds, 类型_ Ty = ··null!(类型_)) {
        if (Ty is ··null!(类型_)) {
            Ty = .cast_!(指针类型_)(.getScalarType(Ptr.类型)).类型;
        }
        类型_ ETy = GEP_.s·getGEPReturnType(Ty, Ptr, Indices);
        GetElementPtrInst I = new GetElementPtrInst();
        I.类型 = ETy;
        .追加!(Value)(I.Ops, Ptr);
        .追加!(Value)(I.Ops, Indices);
        I.InBounds = InBounds;
        I.SourceElementType = Ty;
        I.ResultElementType = ETy;
        return I;
    }
    static ExtractValueInst s·ExtractValue_C(Value Agg, uint[] Indices) {
        类型_ Ty = GEV_.s·getIndexedType(Agg.类型, Indices);
        ExtractValueInst I = new ExtractValueInst();
        I.类型 = Ty;
        I.Ops.length = 1;
        I.Ops[0] = Agg;
        I.Indices = Indices;
        return I;
    }
    static ExtractValueInst s·InsertValue_C(Value Agg, Value Val, uint[] Indices) {
        ExtractValueInst I = new ExtractValueInst();
        I.类型 = Agg.类型;
        I.Ops.length = 2;
        I.Ops[0] = Agg;
        I.Ops[1] = Val;
        I.Indices = Indices;
        return I;
    }
    static GlobalAlias s·GlobalAlias_C(类型_ Ty, uint AddrSpace, LinkageTypes Linkage, Constant Aliasee, ThreadLocalMode_ TLM, VisibilityTypes Visibility, DLLStorageClassTypes DLLStorageClass, UnnamedAddr unnamedAddr, bool DSOLocal, dstring Partition) {
        GlobalAlias I = new GlobalAlias();
        指针类型_ PT = TGet_.s·PtrTy_get(Ty, AddrSpace);
        I.ValueType = Ty;
        I.类型 = PT;
        I.AddrSpace = AddrSpace;
        I.Ops[0] = Aliasee;
        I.TLM = TLM;
        I.Visibility = Visibility;
        I.DllStorageClass = DLLStorageClass;
        I.UnnamedAddrVal = unnamedAddr;
        I.IsDSOLocal = DSOLocal;
        I.Partition = Partition;
        return I;
    }
    static GlobalIFunc s·GlobalIFunc_C(类型_ Ty, uint AddrSpace, LinkageTypes Linkage, Constant Aliasee, ThreadLocalMode_ TLM, VisibilityTypes Visibility, DLLStorageClassTypes DLLStorageClass, UnnamedAddr unnamedAddr, bool DSOLocal, dstring Partition) {
        GlobalIFunc I = new GlobalIFunc();
        指针类型_ PT = TGet_.s·PtrTy_get(Ty, AddrSpace);
        I.类型 = PT;
        I.ValueType = Ty;
        I.AddrSpace = AddrSpace;
        I.Ops[0] = Aliasee;
        I.TLM = TLM;
        I.Visibility = Visibility;
        I.DllStorageClass = DLLStorageClass;
        I.UnnamedAddrVal = unnamedAddr;
        I.IsDSOLocal = DSOLocal;
        I.Partition = Partition;
        return I;
    }
}
uint getPointerAddressSpace(类型_ Ty) {
    return (cast(指针类型_)(.getScalarType(Ty))).地址;
}
Align_ getPointerAlignment(Value V, DataLayout DL) {
    assert(.isPointerTy(V.类型), "must be pointer"c);
    GlobalObject GO = .dyn_cast!(GlobalObject)(V);
    if (GO !is ··null!(GlobalObject)) {
        if (.isFunction(GO)) {
            Align_ FunctionPtrAlign = DL.getFunctionPtrAlign();
            FunctionPtrAlignType k = DL.getFunctionPtrAlignType();
            switch (k) {
                case FunctionPtrAlignType.Independent: {
                    return FunctionPtrAlign;
                }
                case FunctionPtrAlignType.MultipleOfFunctionAlign: {
                    if (FunctionPtrAlign.ShiftValue < GO.Align.ShiftValue) {
                        return FunctionPtrAlign;
                    }
                    return GO.Align;
                }
                default: break;
            }
            assert(false, "Unhandled FunctionPtrAlignType"c);
        }
    }
    ulong AlignmentV = GlobalValue_.s·getAlignment(GO);
    if (AlignmentV != 0) {
        Align_ Alignment = new Align_(AlignmentV);
        GlobalVariable GVar = .dyn_cast!(GlobalVariable)(GO);
        if (GVar !is ··null!(GlobalVariable)) {
            类型_ ObjectType = GVar.类型;
            if (TY_.s·isSized(ObjectType)) {
                if (GlobalValue_.s·isStrongDefinitionForLinker(GVar)) {
                    return DataLayout_.s·getPreferredAlign(DL, GVar);
                }
                else {
                    return DataLayout_.s·getABITypeAlign(DL, ObjectType);
                }
            }
        }
        return Alignment;
    }
    Argument A = .dyn_cast!(Argument)(V);
    if (A !is ··null!(Argument)) {
        Align_ align_ = Argument_.s·getParamAlign(A);
        if (align_ !is ··null!(Align_)) {
            return align_;
        }
        else {
            类型_ EltTy = Argument_.s·hasStructRetAttr(A);
            if ((EltTy !is ··null!(类型_)) && TY_.s·isSized(EltTy)) {
                return DataLayout_.s·getABITypeAlign(DL, EltTy);
            }
            return new Align_();
        }
    }
    AllocaInst AC = .dyn_cast!(AllocaInst)(V);
    if (AC !is ··null!(AllocaInst)) {
        return AC.对齐;
    }
    CallBase CL = .dyn_cast!(CallBase)(V);
    if (CL !is ··null!(CallBase)) {
        Align_ Alignment = RetType_.s·getRetAlign(CL);
        if (Alignment !is ··null!(Align_)) {
            return Alignment;
        }
        else {
            Alignment = RetType_.s·getRetAlignment(CL.getFunc());
        }
        if (Alignment !is ··null!(Align_)) {
            return Alignment;
        }
        return new Align_();
    }
    LoadInst LI = .dyn_cast!(LoadInst)(V);
    if (LI !is ··null!(LoadInst)) {
        return LI.对齐;
    }
    Constant CstPtr = .dyn_cast!(Constant)(V);
    if (CstPtr !is ··null!(Constant)) {
        ConstantInt CstInt = .dyn_cast_or_null!(ConstantInt)(CEGet_.s·getPtrToInt(CstPtr, DataLayout_.s·getIntPtrType(DL, V.类型), true));
        if (CstInt !is ··null!(ConstantInt)) {
            uint TrailingZeros = CstInt.Val.countTrailingZeros();
            ulong 值 = TrailingZeros < .MaxAlignmentExponent ? (cast(ulong)(1)) << TrailingZeros : (cast(ulong)(.MaximumAlignment));
            return new Align_(值);
        }
    }
    return new Align_(1);
}
类型_ 创建内置类型(TypeID_ TypeId) {
    类型_ t = new 类型_((cast(整数_)(类型标志_.内置类型_)));
    .获取类型Id(t);
    t.种类 = TypeId;
    return t;
}
ulong getMDKindID(dstring name) {
    if (CustomMDKindNames.具有(name)) {
        return CustomMDKindNames.获取(name);
    }
    ulong id = (cast(ulong)(CustomMDKindNames.大小()));
    CustomMDKindNames.p·设置(name, id);
    return CustomMDKindNames.获取(name);
}
指针类型_ getUnqualTy(uint 地址) {
    return TGet_.s·PtrTy_get(返回零值!(类型_)(), 地址);
}
bool isPoisonValue(Value V) {
    return V.种类 == ValueTy_.PoisonValueVal;
}
bool isConstantExpr(Value V) {
    ConstantExpr ···temp·0·_5 = (cast(ConstantExpr)(V));
    return ···temp·0·_5 !is ··null!(ConstantExpr);
}
bool isGlobalVariable(Value V) {
    GlobalVariable ···temp·0·_6 = (cast(GlobalVariable)(V));
    return ···temp·0·_6 !is ··null!(GlobalVariable);
}
bool isGlobalValue(Value V) {
    GlobalValue ···temp·0·_7 = (cast(GlobalValue)(V));
    return ···temp·0·_7 !is ··null!(GlobalValue);
}
bool isBlockAddress(Value V) {
    BlockAddress ···temp·0·_8 = (cast(BlockAddress)(V));
    return ···temp·0·_8 !is ··null!(BlockAddress);
}
bool isConstantAggregateZero(Value V) {
    ConstantAggregateZero ···temp·0·_9 = (cast(ConstantAggregateZero)(V));
    return ···temp·0·_9 !is ··null!(ConstantAggregateZero);
}
bool isConstantFP(Value V) {
    ConstantFP ···temp·0·_10 = (cast(ConstantFP)(V));
    return ···temp·0·_10 !is ··null!(ConstantFP);
}
bool isFunction(Value V) {
    Function ···temp·0·_11 = (cast(Function)(V));
    return ···temp·0·_11 !is ··null!(Function);
}
bool isUndefValue(Value V) {
    return V.种类 == ValueTy_.UndefValueVal;
}
bool isConstantVector(Value V) {
    return V.种类 == ValueTy_.ConstantVectorVal;
}
bool isConstantDataVector(Value V) {
    return V.种类 == ValueTy_.ConstantDataVectorVal;
}
bool isConstantInt(Value V) {
    return V.种类 == ValueTy_.ConstantIntVal;
}
bool isStructType(类型_ Ty) {
    return Ty.种类 == TypeID_.StructTyID;
}
bool isHalfTy(类型_ Ty) {
    return Ty.种类 == TypeID_.HalfTyID;
}
bool isFloatTy(类型_ Ty) {
    return Ty.种类 == TypeID_.FloatTyID;
}
bool isDoubleTy(类型_ Ty) {
    return Ty.种类 == TypeID_.DoubleTyID;
}
bool isTokenTy(类型_ Ty) {
    return Ty.种类 == TypeID_.TokenTyID;
}
bool isX86_AMXTy(类型_ Ty) {
    return Ty.种类 == TypeID_.X86_AMXTyID;
}
bool isX86_FP80Ty(类型_ Ty) {
    return Ty.种类 == TypeID_.X86_FP80TyID;
}
bool isFP128Ty(类型_ Ty) {
    return Ty.种类 == TypeID_.FP128TyID;
}
bool isPPC_FP128Ty(类型_ Ty) {
    return Ty.种类 == TypeID_.PPC_FP128TyID;
}
bool isNullValue(Constant Cn) {
    if (Cn.种类 == ValueTy_.ConstantIntVal) {
        return (cast(ConstantInt)(Cn)).Val.isZero();
    }
    if (Cn.种类 == ValueTy_.ConstantFPVal) {
        APFloat_ _0 = new APFloat_((cast(ConstantFP)(Cn)).Val.getSemantics(), "+0.0"d);
        return (cast(ConstantFP)(Cn)).Val.bitwiseIsEqual(_0);
    }
    return Cn.种类 == ValueTy_.ConstantAggregateZeroVal || Cn.种类 == ValueTy_.ConstantPointerNullVal || Cn.种类 == ValueTy_.ConstantTokenNoneVal;
}
bool isGlobalAlias(Value G) {
    return G.种类 == ValueTy_.GlobalAliasVal;
}
bool nullPointerIsDefined(Function F) {
    // return hasFnAttribute(Attribute::NullPointerIsValid);
    return false;
}
bool NullPointerIsDefined(Function F, uint AS) {
    if ((F !is ··null!(Function)) && .nullPointerIsDefined(F)) {
        return true;
    }
    if (AS != 0) {
        return true;
    }
    return false;
}
bool isAllOnesValue(Constant Cn) {
    if (Cn.种类 == ValueTy_.ConstantIntVal) {
        return (cast(ConstantInt)(Cn)).Val.isAllOnesValue();
    }
    if (Cn.种类 == ValueTy_.ConstantFPVal) {
        return (cast(ConstantFP)(Cn)).Val.bitcastToAPInt().isAllOnesValue();
    }
    if (.isVectorType(Cn.类型)) {
        Constant C = .getSplatValue(Cn, false);
        if (C !is ··null!(Constant)) {
            return .isAllOnesValue(C);
        }
    }
    return false;
}
Constant getSplatValue(Constant V, bool AllowUndefs) {
    assert(.isVectorType(V.类型), "Only valid for vectors!"c);
    if (V.种类 == ValueTy_.ConstantAggregateZeroVal) {
        return CGet_.s·getNullValue((cast(向量类型_)(V.类型)).元素类型);
    }
    if (V.种类 == ValueTy_.ConstantDataVectorVal) {
        ConstantDataVector CV = (cast(ConstantDataVector)(V));
        return .ConstantVector_getSplatValue(CV, false);
    }
    if (V.种类 == ValueTy_.ConstantVectorVal) {
        ConstantVector CV = (cast(ConstantVector)(V));
        return .ConstantVector_getSplatValue(CV, AllowUndefs);
    }
    ConstantExpr Shuf = (cast(ConstantExpr)(V));
    if ((Shuf !is ··null!(ConstantExpr)) && Shuf.Opc == InstructionKind_.ShuffleVector && Shuf.Ops[1].种类 == ValueTy_.UndefValueVal) {
        ConstantExpr IElt = (cast(ConstantExpr)(Shuf.Ops[0]));
        if ((IElt !is ··null!(ConstantExpr)) && IElt.Opc == InstructionKind_.InsertElement && IElt.Ops[0].种类 == ValueTy_.UndefValueVal) {
            int[] Mask = (cast(ShuffleVectorConstantExpr)(Shuf)).Mask;
            Constant SplatVal = (cast(Constant)(IElt.Ops[1]));
            ConstantInt Index = (cast(ConstantInt)(IElt.Ops[2]));
            if ((Index !is ··null!(ConstantInt)) && Index.Val.Op等等(0) && 每个!(int)(Mask, (int I) { return I == 0; })) {
                return SplatVal;
            }
        }
    }
    return ··null!(Constant);
}
Constant ConstantVector_getSplatValue(Constant V, bool AllowUndefs) {
    // Check out first element.
    Value Elt = (cast(ConstantExpr)(V)).Ops[0];
    {
        // Then make sure all remaining elements point to the same value.
        for (int i = 1; i < (cast(ConstantAggregate)(V)).Ops.length; ++i) {
            Value OpC = (cast(ConstantAggregate)(V)).Ops[i];
            if (OpC == Elt) {
                continue // Strict mode: any mismatch is not a splat.
                ;
            }
            // Strict mode: any mismatch is not a splat.
            if (!AllowUndefs) {
                return ··null!(Constant);
            }
            // Allow undefs mode: ignore undefined elements.
            if (OpC.种类 == ValueTy_.UndefValueVal) {
                continue // If we do not have a defined element yet, use the current operand.
                ;
            }
            // If we do not have a defined element yet, use the current operand.
            if (Elt.种类 == ValueTy_.UndefValueVal) {
                Elt = OpC;
            }
            if (OpC != Elt) {
                return ··null!(Constant);
            }
        }
    }
    return (cast(Constant)(Elt));
}
Constant getAllOnesValue(类型_ Ty) {
    if (Ty.种类 == TypeID_.IntegerTyID) {
        整数类型_ ITy = (cast(整数类型_)(Ty));
        return CGet_.s·CInt_get(ITy, APInt_getAllOnesValue(ITy.位数));
    }
    if (.isFloatingPointTy(Ty)) {
        APFloat_ FL = APFloat_getAllOnesValue(.getFltSemantics(Ty), (cast(uint)(.getPrimitiveSizeInBits(Ty).getFixedSize())));
        return CGet_.s·CFP_get(FL);
    }
    向量类型_ VTy = (cast(向量类型_)(Ty));
    return CGet_.s·Vector_getSplat(VTy_.s·getElementCount(VTy), .getAllOnesValue(VTy.元素类型));
}
Constant getSequenceIfElementsMatch(Constant[] ES, Constant delegate(类型_, char[]) fn) {
    Constant C = ES[0];
    assert(.isElementTypeCompatible(C.类型), "值错误."c);
    char[] esn = 创建数组!(char)();
    if (C.类型.种类 == TypeID_.IntegerTyID) {
        整数类型_ IT = (cast(整数类型_)(C.类型));
        if (IT.位数 == 8) {
            esn = .getIntSequenceIfElementsMatch!(ubyte)(ES);
        }
        else if (IT.位数 == 16) {
            esn = .getIntSequenceIfElementsMatch!(ushort)(ES);
        }
        else if (IT.位数 == 32) {
            esn = .getIntSequenceIfElementsMatch!(uint)(ES);
        }
        else // 64
         { // 64
            esn = .getIntSequenceIfElementsMatch!(ulong)(ES);
        }
    }
    else if (C.类型.种类 == TypeID_.HalfTyID || C.类型.种类 == TypeID_.BFloatTyID) {
        esn = .getFPSequenceIfElementsMatch!(ushort)(ES);
    }
    else if (C.类型.种类 == TypeID_.FloatTyID) {
        esn = .getFPSequenceIfElementsMatch!(uint)(ES);
    }
    else {
        esn = .getFPSequenceIfElementsMatch!(ulong)(ES);
    }
    return fn(C.类型, esn);
}
T[] crateSmallVector(T)(uint n, T V) {
    T[] arr = 创建数组!(T)();
    arr.length = n;
    {
        for (int i = 0; i < arr.length; ++i) {
            arr[i] = V;
        }
    }
    return arr;
}
char[] getIntSequenceIfElementsMatch(T)(Constant[] ES) {
    char[] esn = 创建数组!(char)();
    foreach (Constant c; ES) {
        APFloat_ i = (cast(ConstantFP)(c)).Val;
        ulong n = i.bitcastToAPInt().getLimitedValue();
        T n16 = (cast(T)(n));
        .追加!(char)(esn, (cast(char[])((cast(byte[])((cast(void[])([n16])))))));
    }
    return esn;
}
char[] 转换为字符8数组(T)(T[] ES) {
    char[] esn = 创建数组!(char)();
    foreach (T c; ES) {
        T n16 = (cast(T)(c));
        .追加!(char)(esn, (cast(char[])((cast(byte[])((cast(void[])([n16])))))));
    }
    return esn;
}
char[] getFPSequenceIfElementsMatch(T)(Constant[] ES) {
    char[] esn = 创建数组!(char)();
    foreach (Constant c; ES) {
        APFloat_ i = (cast(ConstantFP)(c)).Val;
        ulong n = i.bitcastToAPInt().getLimitedValue();
        T n16 = (cast(T)(n));
        .追加!(char)(esn, (cast(char[])((cast(byte[])((cast(void[])([n16])))))));
    }
    return esn;
}
dstring 获取值列表文本Id(Value[] es) {
    dstring[] strs = 映射!(Value, dstring)(es, (Value e, size_t i) { return .获取值文本Id(e) ~ "-"d ~ ·to!(dstring)(i); });
    return 连接(strs, ","d);
}
bool 全是零值(char[] Data) {
    foreach (char ch; Data) {
        if (ch != 字符_.空字符) {
            return false;
        }
    }
    return true;
}
ubyte CastInst_isEliminableCastPair(InstructionKind_ firstOp, InstructionKind_ secondOp, 类型_ SrcTy, 类型_ MidTy, 类型_ DstTy, 类型_ SrcIntPtrTy, 类型_ MidIntPtrTy, 类型_ DstIntPtrTy) {
    static ubyte[][] CastInst_CastResults = [
        // T        F  F  U  S  F  F  P  I  B  A  -+
        // R  Z  S  P  P  I  I  T  P  2  N  T  S   |
        // U  E  E  2  2  2  2  R  E  I  T  C  C   +- secondOp
        // N  X  X  U  S  F  F  N  X  N  2  V  V   |
        // C  T  T  I  I  P  P  C  T  T  P  T  T  -+
        [1, 0, 0, 99, 99, 0, 0, 99, 99, 99, 0, 3, 0],
        [8, 1, 9, 99, 99, 2, 17, 99, 99, 99, 2, 3, 0],
        [8, 0, 1, 99, 99, 0, 2, 99, 99, 99, 0, 3, 0],
        [0, 0, 0, 99, 99, 0, 0, 99, 99, 99, 0, 3, 0],
        [0, 0, 0, 99, 99, 0, 0, 99, 99, 99, 0, 3, 0],
        [99, 99, 99, 0, 0, 99, 99, 0, 0, 99, 99, 4, 0],
        [99, 99, 99, 0, 0, 99, 99, 0, 0, 99, 99, 4, 0],
        [99, 99, 99, 0, 0, 99, 99, 0, 0, 99, 99, 4, 0],
        [99, 99, 99, 2, 2, 99, 99, 8, 2, 99, 99, 4, 0],
        [1, 0, 0, 99, 99, 0, 0, 99, 99, 99, 7, 3, 0],
        [99, 99, 99, 99, 99, 99, 99, 99, 99, 11, 99, 15, 0],
        [5, 5, 5, 6, 6, 5, 5, 6, 6, 16, 5, 1, 14],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 12]
    ];
    bool IsFirstBitcast = (firstOp == InstructionKind_.BitCast);
    bool IsSecondBitcast = (secondOp == InstructionKind_.BitCast);
    bool AreBothBitcasts = IsFirstBitcast && IsSecondBitcast;
    // Check 如果 any of the casts convert scalars <. vectors.
    if ((IsFirstBitcast && .isVectorType(SrcTy) != .isVectorType(MidTy)) || (IsSecondBitcast && .isVectorType(MidTy) != .isVectorType(DstTy))) { }
    ubyte ElimCase = CastInst_CastResults[firstOp - InstructionKind_.CastOpsBegin][secondOp - InstructionKind_.CastOpsBegin];
    switch (ElimCase) {
        case 0: {
            // Categorically disallowed.
            return 0;
        }
        case 1: {
            // Allowed, use first cast_'s opcode.
            return (cast(ubyte)(firstOp));
        }
        case 2: {
            // Allowed, use second cast_'s opcode.
            return (cast(ubyte)(secondOp));
        }
        case 3: {
            // No-op cast_ in second op implies firstOp as long as the DestTy
            // is integer and we are not converting between a vector and a
            // non-vector type.
            if (!.isVectorType(SrcTy) && .isIntegerTy(DstTy)) {
                return (cast(ubyte)(firstOp));
            }
            return 0;
        }
        case 4: {
            // No-op cast_ in second op implies firstOp as long as the DestTy
            // is floating point.
            if (.isFloatingPointTy(DstTy)) {
                return (cast(ubyte)(firstOp));
            }
            return 0;
        }
        case 5: {
            // No-op cast_ in first op implies secondOp as long as the SrcTy
            // is an integer.
            if (.isIntegerTy(SrcTy)) {
                return (cast(ubyte)(secondOp));
            }
            return 0;
        }
        case 6: {
            // No-op cast_ in first op implies secondOp as long as the SrcTy
            // is a floating point.
            if (.isFloatingPointTy(SrcTy)) {
                return (cast(ubyte)(secondOp));
            }
            return 0;
        }
        case 7: {
            // Cannot simplify 如果 address spaces are different!
            if (.getPointerAddressSpace(SrcTy) != .getPointerAddressSpace(DstTy)) {
                return 0;
            }
            ulong MidSize = .getScalarSizeInBits(MidTy);
            // We can still fold this without knowing the actual sizes as long we
            // know that the intermediate pointer is the largest possible
            // pointer size.
            // FIXME: Is this always 真?
            if (MidSize == 64) {
                return (cast(ubyte)(InstructionKind_.BitCast));
            }
            // ptrtoint, inttoptr . bitcast (ptr . ptr) 如果 int size is >= ptr size.
            if ((SrcIntPtrTy is ··null!(类型_)) || DstIntPtrTy != SrcIntPtrTy) {
                return 0;
            }
            ulong PtrSize = .getScalarSizeInBits(SrcIntPtrTy);
            if (MidSize >= PtrSize) {
                return (cast(ubyte)(InstructionKind_.BitCast));
            }
            return 0;
        }
        case 8: {
            // ext, trunc . bitcast,    如果 the SrcTy and DstTy are same size
            // ext, trunc . ext,        如果 sizeof(SrcTy) < sizeof(DstTy)
            // ext, trunc . trunc,      如果 sizeof(SrcTy) > sizeof(DstTy)
            ulong SrcSize = .getScalarSizeInBits(SrcTy);
            ulong DstSize = .getScalarSizeInBits(DstTy);
            if (SrcSize == DstSize) {
                return InstructionKind_.BitCast;
            }
            else if (SrcSize < DstSize) {
                return (cast(ubyte)(firstOp));
            }
            return (cast(ubyte)(secondOp));
        }
        case 9: {
            // zext, sext . zext, because sext can't sign extend after zext
            return (cast(ubyte)(InstructionKind_.ZExt));
        }
        case 11: {
            // inttoptr, ptrtoint . bitcast 如果 SrcSize<=PtrSize and SrcSize==DstSize
            if (MidIntPtrTy is ··null!(类型_)) {
                return 0;
            }
            ulong PtrSize = .getScalarSizeInBits(MidIntPtrTy);
            ulong SrcSize = .getScalarSizeInBits(SrcTy);
            ulong DstSize = .getScalarSizeInBits(DstTy);
            if (SrcSize <= PtrSize && SrcSize == DstSize) {
                return (cast(ubyte)(InstructionKind_.BitCast));
            }
            return 0;
        }
        case 12: {
            // addrspacecast, addrspacecast . bitcast,       如果 SrcAS == DstAS
            // addrspacecast, addrspacecast . addrspacecast, 如果 SrcAS != DstAS
            if (.getPointerAddressSpace(SrcTy) != .getPointerAddressSpace(DstTy)) {
                return InstructionKind_.AddrSpaceCast;
            }
            return (cast(ubyte)(InstructionKind_.BitCast));
        }
        case 13: {
            // FIXME: this state can be merged with (1), but the following 断言
            // is useful to check the correcteness of the sequence due to semantic
            // change of bitcast.
            assert(.isPtrOrPtrVectorTy(SrcTy) && .isPtrOrPtrVectorTy(MidTy) && .isPtrOrPtrVectorTy(DstTy) && .getPointerAddressSpace(SrcTy) != .getPointerAddressSpace(MidTy) && .getPointerAddressSpace(MidTy) == .getPointerAddressSpace(DstTy), "Illegal addrspacecast, bitcast sequence!"c);
            // Allowed, use first cast_'s opcode
            return (cast(ubyte)(firstOp));
        }
        case 14: {
            // bitcast, addrspacecast . addrspacecast 如果 the element type of
            // bitcast's source is the same as that of addrspacecast's destination.
            指针类型_ SrcPtrTy = (cast(指针类型_)(.getScalarType(SrcTy)));
            指针类型_ DstPtrTy = (cast(指针类型_)(.getScalarType(DstTy)));
            if (PTy_.s·hasSameElementTypeAs(SrcPtrTy, DstPtrTy)) {
                return (cast(ubyte)(InstructionKind_.AddrSpaceCast));
            }
            return 0;
        }
        case 15: {
            // FIXME: this state can be merged with (1), but the following 断言
            // is useful to check the correcteness of the sequence due to semantic
            // change of bitcast.
            assert(.isIntOrIntVectorTy(SrcTy) && .isPtrOrPtrVectorTy(MidTy) && .isPtrOrPtrVectorTy(DstTy) && .getPointerAddressSpace(MidTy) == .getPointerAddressSpace(DstTy), "Illegal inttoptr, bitcast sequence!"c);
            // Allowed, use first cast_'s opcode
            return (cast(ubyte)(firstOp));
        }
        case 16: {
            // FIXME: this state can be merged with (2), but the following 断言
            // is useful to check the correcteness of the sequence due to semantic
            // change of bitcast.
            assert(.isPtrOrPtrVectorTy(SrcTy) && .isPtrOrPtrVectorTy(MidTy) && .isIntOrIntVectorTy(DstTy) && .getPointerAddressSpace(SrcTy) == .getPointerAddressSpace(MidTy), "Illegal bitcast, ptrtoint sequence!"c);
            // Allowed, use second cast_'s opcode
            return (cast(ubyte)(secondOp));
        }
        case 17: {
            // (sitofp (zext x)) . (uitofp x)
            return (cast(ubyte)(InstructionKind_.UIToFP));
        }
        case 99: {
            // Cast combination can't happen (error in input). This is for all cases
            // where the MidTy is not the same for the two cast_ instructions.
            assert(false, "Invalid Cast Combination"c);
            break;
        }
        default: {
            assert(false, "Error in CastResults table!!!"c);
            break;
        }
    }
    return 0;
}
T cast_(T)(Object V) {
    return (cast(T)(V));
}
T dyn_cast(T)(Object V) {
    return .cast_!(T)(V);
}
T dyn_cast_or_null(T)(Object V = ··null!(Object)) {
    if (V is ··null!(Object)) {
        return 返回零值!(T)();
    }
    return (cast(T)(V));
}
int[] getShuffleMaskIfValid(ConstantExpr CE) {
    if (CE.Opc == InstructionKind_.ShuffleVector) {
        return (cast(ShuffleVectorConstantExpr)(CE)).Mask;
    }
    return ··null!(int[]);
}
uint[] getIndicesIfValid(ConstantExpr CE) {
    if (CE.Opc == InstructionKind_.ExtractValue) {
        return (cast(ExtractValueConstantExpr)(CE)).Indices;
    }
    if (CE.Opc == InstructionKind_.InsertValue) {
        return (cast(InsertValueConstantExpr)(CE)).Indices;
    }
    return ··null!(uint[]);
}
bool isCompare(ConstantExpr CE) {
    return CE.Opc == InstructionKind_.ICmp || CE.Opc == InstructionKind_.FCmp;
}
类型_ getSourceElementTypeIfValid(ConstantExpr CE) {
    if (CE.Opc == InstructionKind_.GetElementPtr) {
        return (cast(GetElementPtrConstantExpr)(CE)).SrcElementTy;
    }
    return ··null!(类型_);
}
ubyte getPredicate(CompareConstantExpr CE) {
    return CE.predicate;
}
bool InstructionKind_isCast(uint OpCode) {
    return OpCode >= InstructionKind_.CastOpsBegin && OpCode < InstructionKind_.CastOpsEnd;
}
ElementCount Zero_getElementCount(类型_ Ty) {
    数组类型_ AT = (cast(数组类型_)(Ty));
    if (AT !is ··null!(数组类型_)) {
        return ECFixed((cast(uint)(AT.数量)));
    }
    向量类型_ VT = (cast(向量类型_)(Ty));
    if (VT !is ··null!(向量类型_)) {
        return VTy_.s·getElementCount(VT);
    }
    return ECFixed((cast(uint)((cast(结构类型_)(Ty)).ContainedTys.length)));
}
APInt_ getUniqueInteger(Constant V) {
    if (V.种类 == ValueTy_.ConstantIntVal) {
        return (cast(ConstantInt)(V)).Val;
    }
    Constant C = .getAggregateElement(V, 0);
    assert((C !is ··null!(Constant)) && C.种类 == ValueTy_.ConstantIntVal, "xx"c);
    return (cast(ConstantInt)(C)).Val;
}
类型_ getStructElementType(结构类型_ ST, uint index) {
    assert(index < ST.ContainedTys.length, "xx"c);
    return ST_.s·getElementType(ST, (cast(uint)(index)));
}
bool isAggregateType(类型_ Ty) {
    return Ty.种类 == TypeID_.StructTyID || Ty.种类 == TypeID_.ArrayTyID;
}
bool isVectorType(类型_ Ty) {
    return Ty.种类 == TypeID_.FixedVectorTyID || Ty.种类 == TypeID_.ScalableVectorTyID;
}
bool isScalableVectorType(类型_ Ty) {
    return Ty.种类 == TypeID_.ScalableVectorTyID;
}
bool isFixedVectorType(类型_ Ty) {
    return Ty.种类 == TypeID_.FixedVectorTyID;
}
bool isConstantPointerNull(Value V) {
    return V.种类 == ValueTy_.ConstantPointerNullVal;
}
bool isIntOrPtrTy(类型_ Ty) {
    return .isIntegerTy(Ty) || .isPointerTy(Ty);
}
bool isIntegerTy(类型_ Ty, uint 位数 = ··null!(uint)) {
    return Ty.种类 == TypeID_.IntegerTyID && (位数 == 0 || (cast(整数类型_)(Ty)).位数 == 位数);
}
bool isPointerTy(类型_ Ty) {
    return Ty.种类 == TypeID_.PointerTyID;
}
bool isIntOrIntVectorTy(类型_ Ty, uint 位数 = ··null!(uint)) {
    return .isIntegerTy(.getScalarType(Ty), 位数);
}
bool isFPOrFPVectorTy(类型_ Ty) {
    return .isFloatingPointTy(.getScalarType(Ty));
}
bool isPtrOrPtrVectorTy(类型_ Ty) {
    return .getScalarType(Ty).种类 == TypeID_.PointerTyID;
}
bool isFunctionTy(类型_ Ty) {
    return Ty.种类 == TypeID_.FunctionTyID;
}
bool isLabelTy(类型_ Ty) {
    return Ty.种类 == TypeID_.LabelTyID;
}
bool isMetadataTy(类型_ Ty) {
    return Ty.种类 == TypeID_.MetadataTyID;
}
bool isValidReturnType(类型_ RetTy) {
    return !.isFunctionTy(RetTy) && !.isLabelTy(RetTy) && !.isMetadataTy(RetTy);
}
TypeSize getPrimitiveSizeInBits(类型_ Ty) {
    switch (Ty.种类) {
        case TypeID_.HalfTyID: {
            return Fixed(16);
        }
        case TypeID_.BFloatTyID: {
            return Fixed(16);
        }
        case TypeID_.FloatTyID: {
            return Fixed(32);
        }
        case TypeID_.DoubleTyID: {
            return Fixed(64);
        }
        case TypeID_.X86_FP80TyID: {
            return Fixed(80);
        }
        case TypeID_.FP128TyID: {
            return Fixed(128);
        }
        case TypeID_.PPC_FP128TyID: {
            return Fixed(128);
        }
        case TypeID_.X86_MMXTyID: {
            return Fixed(64);
        }
        case TypeID_.X86_AMXTyID: {
            return Fixed(8192);
        }
        case TypeID_.IntegerTyID: {
            return Fixed((cast(整数类型_)(Ty)).位数);
        }
        case TypeID_.FixedVectorTyID:
        case TypeID_.ScalableVectorTyID: {
            向量类型_ VTy = (cast(向量类型_)(Ty));
            ElementCount EC = VTy_.s·getElementCount(VTy);
            TypeSize ETS = .getPrimitiveSizeInBits(VTy.元素类型);
            assert(!ETS.isScalable(), "Vector type should have fixed-width elements"c);
            return new TypeSize(ETS.getFixedSize() * EC.getKnownMinValue(), EC.isScalable());
        }
        default: {
            return Fixed(0);
        }
    }
}
int IdxCompare(Constant C1, Constant C2, 类型_ ElTy) {
    if (C1 == C2) {
        return 0;
    }
    // Ok, we found a d如果ferent index.  如果 they are not ConstantInt, we can't do
    // anything with them.
    if (!.isConstantInt(C1) || !.isConstantInt(C2)) {
        return -2;
    } // don't know!
    // We cannot compare the indices 如果 they don't fit in an int64_t.
    if (.cast_!(ConstantInt)(C1).Val.getActiveBits() > 64 || .cast_!(ConstantInt)(C2).Val.getActiveBits() > 64) {
        return -2;
    } // don't know!
    // Ok, we have two d如果fering integer indices.  Sign extend them to be the same
    // type.
    long C1Val = .cast_!(ConstantInt)(C1).Val.getSExtValue();
    long C2Val = .cast_!(ConstantInt)(C2).Val.getSExtValue();
    if (C1Val == C2Val) {
        return // They are equal
         0;
    } // They are equal
    // 如果 the type being indexed over is really just a zero sized type, there is
    // no pointer d如果ference being made here.
    if (.isMaybeZeroSizedType(ElTy)) {
        return -2;
    } // dunno.
    // 如果 they are really d如果ferent, now that they are the same type, then we
    // found a d如果ference!
    if (C1Val < C2Val) {
        return -1;
    }
    else {
        return 1;
    }
}
bool isMaybeZeroSizedType(类型_ Ty) {
    结构类型_ STy = .dyn_cast!(结构类型_)(Ty);
    if (STy !is ··null!(结构类型_)) {
        if (ST_.s·isOpaque(STy)) {
            return // Can't say.
             true;
        } // Can't say.
        {
            // If all of elements have zero size, this does too.
            for (int i = 0; i < ST_.s·getNumElements(STy); ++i) {
                if (!.isMaybeZeroSizedType(ST_.s·getElementType(STy, i))) {
                    return false;
                }
            }
        }
        return true;
    }
    else if (.dyn_cast!(数组类型_)(Ty) !is ··null!(数组类型_)) {
        数组类型_ ATy = .dyn_cast!(数组类型_)(Ty);
        return .isMaybeZeroSizedType(ATy.元素类型);
    }
    return false;
}
类型_ getScalarType(类型_ Ty) {
    if (.isVectorType(Ty)) {
        return (cast(向量类型_)(Ty)).元素类型;
    }
    return Ty;
}
ulong getScalarSizeInBits(类型_ Ty) {
    return .getPrimitiveSizeInBits(.getScalarType(Ty)).getFixedSize();
}
uint getAddressSpace(指针类型_ Ty) {
    return Ty.地址;
}
/* 转换是有效的 */
bool castIsValid(InstructionKind_ op, 类型_ SrcTy, 类型_ DstTy) {
    if (!.isFirstClassType(SrcTy) || !.isFirstClassType(DstTy) || .isAggregateType(SrcTy) || .isAggregateType(DstTy)) {
        return false;
    }
    bool SrcIsVec = .isVectorType(SrcTy);
    bool DstIsVec = .isVectorType(DstTy);
    ulong SrcScalarBitSize = .getScalarSizeInBits(SrcTy);
    ulong DstScalarBitSize = .getScalarSizeInBits(DstTy);
    ElementCount SrcEC = SrcIsVec ? VTy_.s·getElementCount((cast(向量类型_)(SrcTy))) : new ElementCount(0, false);
    ElementCount DstEC = DstIsVec ? VTy_.s·getElementCount((cast(向量类型_)(DstTy))) : new ElementCount(0, false);
    switch (op) {
        case InstructionKind_.Trunc: {
            return .isIntOrIntVectorTy(SrcTy) && .isIntOrIntVectorTy(DstTy) && SrcEC.p·Op等等(DstEC) && SrcScalarBitSize > DstScalarBitSize;
        }
        case InstructionKind_.ZExt: {
            return .isIntOrIntVectorTy(SrcTy) && .isIntOrIntVectorTy(DstTy) && SrcEC.p·Op等等(DstEC) && SrcScalarBitSize < DstScalarBitSize;
        }
        case InstructionKind_.SExt: {
            return .isIntOrIntVectorTy(SrcTy) && .isIntOrIntVectorTy(DstTy) && SrcEC.p·Op等等(DstEC) && SrcScalarBitSize < DstScalarBitSize;
        }
        case InstructionKind_.FPTrunc: {
            return .isFPOrFPVectorTy(SrcTy) && .isFPOrFPVectorTy(DstTy) && SrcEC.p·Op等等(DstEC) && SrcScalarBitSize > DstScalarBitSize;
        }
        case InstructionKind_.FPExt: {
            return .isFPOrFPVectorTy(SrcTy) && .isFPOrFPVectorTy(DstTy) && SrcEC.p·Op等等(DstEC) && SrcScalarBitSize < DstScalarBitSize;
        }
        case InstructionKind_.UIToFP:
        case InstructionKind_.SIToFP: {
            return .isIntOrIntVectorTy(SrcTy) && .isFPOrFPVectorTy(DstTy) && SrcEC.p·Op等等(DstEC);
        }
        case InstructionKind_.FPToUI:
        case InstructionKind_.FPToSI: {
            return .isFPOrFPVectorTy(SrcTy) && .isIntOrIntVectorTy(DstTy) && SrcEC.p·Op等等(DstEC);
        }
        case InstructionKind_.PtrToInt: {
            if (!SrcEC.p·Op等等(DstEC)) {
                return false;
            }
            return .isPtrOrPtrVectorTy(SrcTy) && .isIntOrIntVectorTy(DstTy);
        }
        case InstructionKind_.IntToPtr: {
            if (!SrcEC.p·Op等等(DstEC)) {
                return false;
            }
            return .isIntOrIntVectorTy(SrcTy) && .isPtrOrPtrVectorTy(DstTy);
        }
        case InstructionKind_.BitCast: {
            指针类型_ SrcPtrTy = (cast(指针类型_)(.getScalarType(SrcTy)));
            指针类型_ DstPtrTy = (cast(指针类型_)(.getScalarType(DstTy)));
            // BitCast implies a no-op cast_ of type only. No bits change.
            // However, you can't cast_ pointers to anything but pointers.
            if ((SrcPtrTy is ··null!(指针类型_)) != (DstPtrTy is ··null!(指针类型_))) {
                return false;
            }
            // For non-pointer cases, the cast_ is okay 如果 the source and destination bit
            // widths are identical.
            if (SrcPtrTy is ··null!(指针类型_)) {
                return .getPrimitiveSizeInBits(SrcTy) == .getPrimitiveSizeInBits(DstTy);
            }
            // If both are pointers then the address spaces must match.
            if (.getAddressSpace(SrcPtrTy) != .getAddressSpace(DstPtrTy)) {
                return false;
            }
            // A vector of pointers must have the same number of elements.
            if (SrcIsVec && DstIsVec) {
                return SrcEC.p·Op等等(DstEC);
            }
            if (SrcIsVec) {
                return SrcEC.p·Op等等(new ElementCount(1, false));
            }
            if (DstIsVec) {
                return DstEC.p·Op等等(new ElementCount(1, false));
            }
            return true;
        }
        case InstructionKind_.AddrSpaceCast: {
            指针类型_ SrcPtrTy = (cast(指针类型_)(.getScalarType(SrcTy)));
            if (SrcPtrTy is ··null!(指针类型_)) {
                return false;
            }
            指针类型_ DstPtrTy = (cast(指针类型_)(.getScalarType(DstTy)));
            if (DstPtrTy is ··null!(指针类型_)) {
                return false;
            }
            if (.getAddressSpace(SrcPtrTy) == .getAddressSpace(DstPtrTy)) {
                return false;
            }
            return SrcEC.p·Op等等(DstEC);
        }
        default: break;
    }
    return false;
}
Constant getAggregateElement(Constant C, uint Elt) {
    ConstantAggregate CC = (cast(ConstantAggregate)(C));
    if (CC !is ··null!(ConstantAggregate)) {
        if (Elt < CC.Ops.length) {
            return (cast(Constant)(CC.Ops[Elt]));
        }
        return ··null!(Constant);
    }
    ConstantAggregateZero CAZ = (cast(ConstantAggregateZero)(C));
    if (CAZ !is ··null!(ConstantAggregateZero)) {
        ElementCount 元素数量 = .Zero_getElementCount(CAZ.类型);
        if (Elt < 元素数量.getKnownMinValue()) {
            return CAZero_.s·getElementValue(CAZ.类型, Elt);
        }
    }
    if (C.类型.种类 == TypeID_.ScalableVectorTyID) {
        return ··null!(Constant);
    }
    PoisonValue PV = (cast(PoisonValue)(C));
    if (PV !is ··null!(PoisonValue)) {
        ElementCount 元素数量 = .Zero_getElementCount(PV.类型);
        if (Elt < 元素数量.getKnownMinValue()) {
            return PoV_.s·getElementValue_1(PV.类型, Elt);
        }
        return ··null!(Constant);
    }
    UndefValue UV = (cast(UndefValue)(C));
    if (UV !is ··null!(UndefValue)) {
        ElementCount 元素数量 = .Zero_getElementCount(PV.类型);
        if (Elt < 元素数量.getKnownMinValue()) {
            return UnV_.s·getElementValue(PV.类型, Elt);
        }
        return ··null!(Constant);
    }
    ConstantDataSequential CDS = (cast(ConstantDataSequential)(C));
    if (CDS !is ··null!(ConstantDataSequential)) {
        ElementCount 元素数量 = .Zero_getElementCount(PV.类型);
        if (Elt < 元素数量.getKnownMinValue()) {
            return CDS_.s·getElementAsConstant(CDS, Elt);
        }
        return ··null!(Constant);
    }
    return ··null!(Constant);
}
Constant getAggregateElement_2(Constant C, Constant Elt) {
    ConstantInt CI = .dyn_cast!(ConstantInt)(Elt);
    if (CI !is ··null!(ConstantInt)) {
        if (CI.Val.getActiveBits() > 64) {
            return ··null!(Constant);
        }
        return .getAggregateElement(C, (cast(uint)(CI.Val.getZExtValue())));
    }
    return ··null!(Constant);
}
T 转换枚举(T)(uint opc) {
    return (cast(T)(opc));
}
bool is_splat(T)(T[] Range) {
    size_t range_size = Range.length;
    return range_size != 0 && (range_size == 1 || 每个数组成员!(T)(Range[1 .. $], (T v, size_t _) { return v == Range[0]; }));
}
bool isIndexInRangeOfArrayType(ulong NumElements, ConstantInt CI) {
    // We cannot bounds check the index if it doesn't fit in an int64_t.
    if (CI.Val.getMinSignedBits() > 64) {
        return false;
    }
    // A negative index or an index past the end of our sequential type is
    // considered out-of-range.
    long IndexVal = CI.Val.getSExtValue();
    if (IndexVal < 0 || (NumElements > 0 && (cast(ulong)(IndexVal)) >= NumElements)) {
        return false;
    }
    // Otherwise, it is in-range.
    return true;
}
bool containsConstantExpression(Constant V) {
    向量类型_ VTy = .dyn_cast!(向量类型_)(V.类型);
    if (VTy !is ··null!(向量类型_)) {
        {
            for (uint i = 0; i < VTy.数量; ++i) {
                if (.isConstantExpr(.getAggregateElement(V, i))) {
                    return true;
                }
            }
        }
    }
    return false;
}
bool containsPoisonElement(Constant V) {
    return .containsUndefinedElement(V, (Constant c) { return .isPoisonValue(c); });
}
bool containsUndefinedElement(Constant C, bool delegate(Constant) HasFn) {
    向量类型_ VTy = .dyn_cast!(向量类型_)(C.类型);
    if (VTy !is ··null!(向量类型_)) {
        if (HasFn(C)) {
            return true;
        }
        if (.isConstantAggregateZero(C)) {
            return false;
        }
        if (.isScalableVectorType(C.类型)) {
            return false;
        }
        {
            for (uint i = 0; i < VTy.数量; ++i) {
                if (HasFn(.getAggregateElement(C, i))) {
                    return true;
                }
            }
        }
    }
    return false;
}
bool hasExternalWeakLinkage(Value GV) {
    return false;
}
bool isInBoundsIndices(Value[] Idxs) {
    // No indices means nothing that could be out of bounds.
    if ((Idxs is ··null!(Value[])) || Idxs.length == 0) {
        return true;
    }
    // If the first index is zero, it's in bounds.
    if (.isNullValue(.cast_!(Constant)(Idxs[0]))) {
        return true;
    }
    // If the first index is one and all the rest are zero, it's in bounds,
    // by the one-past-the-end rule.
    ConstantInt CI = .cast_!(ConstantInt)(Idxs[0]);
    if (CI !is ··null!(ConstantInt)) {
        if (!CI.Val.isOneValue()) {
            return false;
        }
    }
    else {
        ConstantDataVector CV = .cast_!(ConstantDataVector)(Idxs[0]);
        CI = .dyn_cast_or_null!(ConstantInt)(.getSplatValue(CV, false));
        if ((CI is ··null!(ConstantInt)) || !CI.Val.isOneValue()) {
            return false;
        }
    }
    {
        for (int i = 1; i < Idxs.length; ++i) {
            if (!.isNullValue(.cast_!(Constant)(Idxs[i]))) {
                return false;
            }
        }
    }
    return true;
}
dstring SelectInst_areInvalidOperands(Value Op0, Value Op1, Value Op2) {
    if (Op1.类型 != Op2.类型) {
        return "both values to select must have same type"d;
    }
    if (.isTokenTy(Op1.类型)) {
        return "select values cannot have token type"d;
    }
    向量类型_ VT = .dyn_cast!(向量类型_)(Op0.类型);
    if (VT !is ··null!(向量类型_)) {
        if (VT.元素类型 != TGet_.s·IntTy_get(1)) {
            return "vector select condition element type must be i1"d;
        }
        向量类型_ ET = .dyn_cast!(向量类型_)(Op1.类型);
        if (ET is ··null!(向量类型_)) {
            return "selected values for vector select must be vectors"d;
        }
        if (!VTy_.s·getElementCount(ET).p·Op等等(VTy_.s·getElementCount(VT))) {
            return "vector select requires selected vectors to have, the same vector length as select condition"d;
        }
    }
    else if (Op0.类型 != TGet_.s·IntTy_get(1)) {
        return "select condition must be i1 or <n x i1>"d;
    }
    return ··null!(dstring);
}
bool isPowerOf2(APInt_ V) {
    return true;
}
bool match(Value C, Match_ ma) {
    return ma.match(C);
}
cst_pred_ty!(is_neg_zero_fp, ConstantFP) m_NegZeroFP() {
    return new cst_pred_ty!(is_neg_zero_fp, ConstantFP)(new is_neg_zero_fp());
}
cst_pred_ty!(is_one, ConstantInt) m_One() {
    return new cst_pred_ty!(is_one, ConstantInt)(new is_one());
}
is_zero m_Zero() {
    return new is_zero();
}
undef_match m_Undef() {
    return new undef_match();
}
match_combine_or m_CombineOr(Match_ L, Match_ R) {
    return new match_combine_or(L, R);
}
apint_match_ m_APInt(APInt_* c) {
    return new apint_match_(c);
}
Constant ConstantFP_getNegativeZero(类型_ Ty) {
    FltSemantics_ Semantics = .getFltSemantics(.getScalarType(Ty));
    APFloat_ NegZero = APFloat_getZero(Semantics, /*Negative=*/ true);
    ConstantFP C = CGet_.s·CFP_get(NegZero);
    向量类型_ VTy = .dyn_cast!(向量类型_)(Ty);
    if (VTy !is ··null!(向量类型_)) {
        return CGet_.s·Vector_getSplat(VTy_.s·getElementCount(VTy), C);
    }
    return C;
}
Constant ConstantFP_getZeroValueForNegation(类型_ Ty) {
    if (.isFPOrFPVectorTy(Ty)) {
        return .ConstantFP_getNegativeZero(Ty);
    }
    return CGet_.s·getNullValue(Ty);
}
指针类型_ PtrTy_getWithSamePointeeType(指针类型_ PT, uint 地址) {
    if (PTy_.s·isOpaque(PT)) {
        return TGet_.s·PtrTy_get(返回零值!(类型_)(), 地址);
    }
    return TGet_.s·PtrTy_get(PT.类型, 地址);
}
bool rangeOnlyContains(Constant[] V, Constant C) {
    foreach (Constant v; V) {
        if (v != C) {
            return false;
        }
    }
    return true;
}
类型_ getFloatingPointTy(FltSemantics_ S) {
    类型_ Ty;
    if (S == IEEEhalf()) {
        Ty = .HalfTy;
    }
    else if (S == BFloat()) {
        Ty = .BFloatTy;
    }
    else if (S == IEEEsingle()) {
        Ty = .FloatTy;
    }
    else if (S == IEEEdouble()) {
        Ty = .DoubleTy;
    }
    else if (S == x87DoubleExtended()) {
        Ty = .X86_FP80Ty;
    }
    else if (S == IEEEquad()) {
        Ty = .FP128Ty;
    }
    else {
        Ty = .PPC_FP128Ty;
    }
    return Ty;
}
FltSemantics_ getFltSemantics(类型_ Ty) {
    if (Ty == .HalfTy) {
        return IEEEhalf();
    }
    else if (Ty == .BFloatTy) {
        return BFloat();
    }
    else if (Ty == .FloatTy) {
        return IEEEsingle();
    }
    else if (Ty == .DoubleTy) {
        return IEEEdouble();
    }
    else if (Ty == .X86_FP80Ty) {
        return x87DoubleExtended();
    }
    else if (Ty == .FP128Ty) {
        return IEEEquad();
    }
    else {
        return PPCDoubleDouble();
    }
}
dstring 获取类型列表的文本Id(类型_[] 类型组) {
    dstring[] ks = 映射!(类型_, dstring)(类型组, (类型_ t, size_t _) { return .获取类型文本Id(t); });
    return 连接(ks, "-"d);
}
dstring 获取值文本Id(Value Val) {
    return ·to!(dstring)(.获取值Id(Val));
}
long 获取值Id(Value Val) {
    if (Val.id == 0) {
        Val.id = .下个Id;
        ++下个Id;
    }
    return Val.id;
}
long 获取节点Id(基础节点.节点_ node) {
    if (node.id == 0) {
        node.id = .下个Id;
        ++下个Id;
    }
    return node.id;
}
dstring 获取节点文本Id(基础节点.节点_ node) {
    return ·to!(dstring)(.获取节点Id(node));
}
long 获取类型Id(类型_ 类型) {
    if (类型.id == 0) {
        类型.id = .下个Id;
        ++下个Id;
    }
    return 类型.id;
}
dstring 获取类型文本Id(类型_ 类型) {
    return ·to!(dstring)(.获取类型Id(类型));
}
SValue 获取符号解析值(基础符号_ 符号) {
    if (符号.扩展 is ··null!(void*)) {
        符号.扩展 = (cast(void*)(.创建符号解析值(符号)));
    }
    return (cast(SValue)(符号.扩展));
}
SValue 创建符号解析值(基础符号_ 符号) {
    return new SValue((cast(符号_)(符号)));
}
T 获取节点解析值(T)(基础节点.节点_ 节点) {
    if (节点.扩展 is ··null!(void*)) {
        节点.扩展 = (cast(void*)(.创建解析值!(T)()));
    }
    Value V = (cast(Value)(节点.扩展));
    return (cast(T)(V));
}
T 有解析值(T)(基础节点.节点_ 节点) {
    if (节点.扩展 !is ··null!(void*)) {
        Value V = (cast(Value)(节点.扩展));
        return (cast(T)(V));
    }
    return 返回零值!(T)();
}
void 设置解析值(基础节点.节点_ 节点, Value V, bool 覆盖 = false) {
    if (!覆盖) {
        assert(节点.扩展 is ··null!(void*), "已经具有值"c);
    }
    节点.扩展 = (cast(void*)(V));
}
Value 创建解析值(T)() {
    Value V = new T();
    return (cast(Value)(V));
}
符号_ 获取符号(符号表_ 符号表, dstring 名称, 符号标志_ 标志) {
    if ((符号表 !is null) && (符号表.原型 !is ··null!(基础符号_[dstring])) && 符号表.具有(名称)) {
        基础符号_ 符号 = 符号表.获取(名称);
        if ((符号.标志 & 标志) != 0) {
            return (cast(符号_)(符号));
        }
    }
    return ··null!(符号_);
}
符号_ 解析名称(节点_ 位置, dstring 名称, 符号标志_ 意义, 节点_ 名称参数 = ··null!(节点_), 诊断消息_ 失败消息 = ··null!(诊断消息_), bool 是使用 = false) {
    return .解析名称助手(位置, 名称, 意义, 名称参数, 失败消息, 是使用);
}
符号_ 解析名称助手(基础节点.节点_ 位置, dstring 名称, 符号标志_ 意义, 基础节点.节点_ 名称参数 = ··null!(基础节点.节点_), 诊断消息_ 失败消息 = ··null!(诊断消息_), bool 是使用 = false, 获取符号_ 获取 = cast(获取符号_)(·fd(&.获取符号))) {
    if (位置 is ··null!(基础节点.节点_)) {
        return ··null!(符号_);
    }
    基础节点.节点_ 原始位置 = 位置;
    符号_ result;
    if ((意义 & (符号标志_.类型声明_)) != 0) {
        if ((当前源文件.类型组 is null) || (当前源文件.类型组.原型 is ··null!(基础符号_[dstring]))) {
            return ··null!(符号_);
        }
        result = 获取(当前源文件.类型组, 名称, 意义);
    }
    else if ((意义 & (符号标志_.特性声明_)) != 0) {
        if ((当前源文件.特性组 is null) || (当前源文件.特性组.原型 is ··null!(基础符号_[dstring]))) {
            return ··null!(符号_);
        }
        result = 获取(当前源文件.特性组, 名称, 意义);
    }
    else if ((意义 & (符号标志_.封装声明_)) != 0) {
        if ((当前源文件.封装组 is null) || (当前源文件.封装组.原型 is ··null!(基础符号_[dstring]))) {
            return ··null!(符号_);
        }
        result = 获取(当前源文件.封装组, 名称, 意义);
    }
    else if ((意义 & (符号标志_.独立元数据_ | 符号标志_.命名元数据_)) != 0) {
        if ((当前源文件.元数据 is null) || (当前源文件.元数据.原型 is ··null!(基础符号_[dstring]))) {
            return ··null!(符号_);
        }
        result = 获取(当前源文件.元数据, 名称, 意义);
    }
    else if ((意义 & (符号标志_.摘要声明_)) != 0) {
        if ((当前源文件.元数据 is null) || (当前源文件.元数据.原型 is ··null!(基础符号_[dstring]))) {
            return ··null!(符号_);
        }
        result = 获取(当前源文件.摘要组, 名称, 意义);
    }
    else {
        while(位置 !is ··null!(基础节点.节点_)) {
            if ((位置.本地组 !is null) && (位置.本地组.原型 !is ··null!(基础符号_[dstring]))) {
                result = 获取(位置.本地组, 名称, 意义);
                if (result !is ··null!(符号_)) {
                    break;
                }
            }
            位置 = 位置.父节点;
        }
    }
    if (是使用 && (result !is ··null!(符号_))) {
        result.isReferenced |= 意义;
        if ((result.引用者集合 is null) || (result.引用者集合.原型 is ··null!(基础节点.节点_[dstring]))) {
            result.引用者集合 = new 词典_!(基础节点.节点_)();
        }
        dstring k = .获取节点文本Id(原始位置);
        if (!result.引用者集合.具有(k)) {
            result.引用者集合.p·设置(k, 原始位置);
        }
    }
    if ((result is ··null!(符号_)) && (失败消息 !is ··null!(诊断消息_))) {
        基础节点.节点_ 错误位置 = 名称参数;
        if (错误位置 is ··null!(基础节点.节点_)) {
            错误位置 = 原始位置;
        }
        .错误(错误位置, 失败消息, 名称);
    }
    if ((result !is ··null!(符号_)) && (意义 & 符号标志_.类型_) != 0) {
        if (.检查正向引用(result, 原始位置)) {
            return ··null!(符号_);
        }
    }
    return result;
}
bool 检查正向引用(符号_ 符号, 基础节点.节点_ 位置) {
    基础节点.节点_ 类型声明 = 查找祖先(位置, (基础节点_ n) {
        if (n.目标种类 == ISK.函数声明 || n.目标种类 == ISK.函数定义 || n.目标种类 == ISK.源文件) {
            return 三元结果_.初始_;
        }
        if (n.目标种类 == ISK.类型声明) {
            return 三元结果_.真_;
        }
        return 三元结果_.假_;
    });
    if (类型声明 !is ··null!(基础节点.节点_)) {
        类型声明_ decT = (cast(类型声明_)(类型声明));
        if (decT.类型.目标种类 != ISK.结构类型) {
            if (位置.开始 >= decT.类型.开始 && 位置.结束 <= decT.结束) {
                // 位置 是类型声明的 类型节点内;
                基础节点.节点_ dec = 符号.声明组[0];
                if ((dec !is ··null!(基础节点.节点_)) && dec.开始 >= 类型声明.结束) {
                    .错误(位置, 诊断集_.非结构类型正向引用错误);
                    return true;
                }
            }
        }
    }
    return false;
}
诊断_ 错误(基础节点.节点_ location = ··null!(基础节点.节点_), 诊断消息_ message = ··null!(诊断消息_), dstring arg0 = ··null!(dstring), dstring arg1 = ··null!(dstring), dstring arg2 = ··null!(dstring), dstring arg3 = ··null!(dstring), dstring arg4 = ··null!(dstring)) {
    诊断_ diagnostic = location ? 创建节点的诊断(location, message, [arg0, arg1, arg2, arg3, arg4]) : 创建编译诊断(message, [arg0, arg1, arg2, arg3, arg4]);
    诊断集.add(diagnostic);
    return diagnostic;
}
bool 加入类型决议(语法系统_ 目标, 类型系统名称_ 名称) {
    long resolutionCycleStartIndex = .findResolutionCycleStartIndex(目标, 名称);
    if (resolutionCycleStartIndex >= 0) {
        // A cycle was found
        size_t 长度 = resolutionTargets.length;
        {
            for (long i = resolutionCycleStartIndex; i < 长度; ++i) {
                resolutionResults[i] = false;
            }
        }
        return false;
    }
    .追加!(语法系统_)(.resolutionTargets, 目标);
    .追加!(bool)(.resolutionResults, true);
    .追加!(类型系统名称_)(.resolutionPropertyNames, 名称);
    return true;
}
bool 弹出类型决议() {
    if (resolutionTargets.length > 0) {
        resolutionTargets.length = resolutionTargets.length - 1;
    }
    if (resolutionPropertyNames.length > 0) {
        resolutionPropertyNames.length = resolutionPropertyNames.length - 1;
    }
    if (resolutionResults.length > 0) {
        bool 结果 = resolutionResults[resolutionResults.length - 1];
        resolutionResults.length = resolutionResults.length - 1;
        return 结果;
    }
    return false;
}
long findResolutionCycleStartIndex(语法系统_ target, 类型系统名称_ propertyName) {
    {
        for (long i = resolutionTargets.length - 1; i >= 0; --i) {
            if (.有类型(resolutionTargets[i], resolutionPropertyNames[i])) {
                return -1;
            }
            if (resolutionTargets[i] == target && resolutionPropertyNames[i] == propertyName) {
                return i;
            }
        }
    }
    return -1;
}
bool 有类型(语法系统_ target, 类型系统名称_ propertyName) {
    switch (propertyName) {
        case 类型系统名称_.类型_: {
            符号_ ···temp·0·_12 = (cast(符号_)(target));
            return (···temp·0·_12 !is ··null!(符号_)) && (((cast(符号_)(target)).类型) !is ··null!(类型_));
        }
        default: {
            符号_ ···temp·0·_13 = (cast(符号_)(target));
            return (···temp·0·_13 !is ··null!(符号_)) && (((cast(符号_)(target)).声明类型) !is ··null!(类型_));
        }
    }
}
bool hasAttributeProperty(AttrKind_ Kind, 特性属性_ Prop) {
    int Index = Kind - 1;
    return (特性属性表[Index] & Prop) != 0;
}
bool canUseAsFnAttr(AttrKind_ Kind) {
    return .hasAttributeProperty(Kind, 特性属性_.FnAttr);
}
bool canUseAsParamAttr(AttrKind_ Kind) {
    return .hasAttributeProperty(Kind, 特性属性_.ParamAttr);
}
bool canUseAsRetAttr(AttrKind_ Kind) {
    return .hasAttributeProperty(Kind, 特性属性_.RetAttr);
}
bool 是特性语法(ISK kind) {
    if (kind == ISK.StringConstant) {
        return true;
    }
    AttrKind_ k = .tokenToAttribute(kind);
    return k != AttrKind_.None;
}
AttrKind_ tokenToAttribute(long isk) {
    switch (isk) {
        case ISK.alwaysinline: {
            return AttrKind_.AlwaysInline;
        }
        case ISK.argmemonly: {
            return AttrKind_.ArgMemOnly;
        }
        case ISK.builtin: {
            return AttrKind_.Builtin;
        }
        case ISK.cold: {
            return AttrKind_.Cold;
        }
        case ISK.convergent: {
            return AttrKind_.Convergent;
        }
        case ISK.disable_sanitizer_instrumentation: {
            return AttrKind_.DisableSanitizerInstrumentation;
        }
        case ISK.hot: {
            return AttrKind_.Hot;
        }
        case ISK.immarg: {
            return AttrKind_.ImmArg;
        }
        case ISK.inreg: {
            return AttrKind_.InReg;
        }
        case ISK.inaccessiblememonly: {
            return AttrKind_.InaccessibleMemOnly;
        }
        case ISK.inaccessiblemem_or_argmemonly: {
            return AttrKind_.InaccessibleMemOrArgMemOnly;
        }
        case ISK.inlinehint: {
            return AttrKind_.InlineHint;
        }
        case ISK.jumptable: {
            return AttrKind_.JumpTable;
        }
        case ISK.minsize: {
            return AttrKind_.MinSize;
        }
        case ISK.mustprogress: {
            return AttrKind_.MustProgress;
        }
        case ISK.naked: {
            return AttrKind_.Naked;
        }
        case ISK.nest: {
            return AttrKind_.Nest;
        }
        case ISK.noalias: {
            return AttrKind_.NoAlias;
        }
        case ISK.nobuiltin: {
            return AttrKind_.NoBuiltin;
        }
        case ISK.nocallback: {
            return AttrKind_.NoCallback;
        }
        case ISK.nocapture: {
            return AttrKind_.NoCapture;
        }
        case ISK.nocf_check: {
            return AttrKind_.NoCfCheck;
        }
        case ISK.noduplicate: {
            return AttrKind_.NoDuplicate;
        }
        case ISK.nofree: {
            return AttrKind_.NoFree;
        }
        case ISK.noimplicitfloat: {
            return AttrKind_.NoImplicitFloat;
        }
        case ISK.noinline: {
            return AttrKind_.NoInline;
        }
        case ISK.nomerge: {
            return AttrKind_.NoMerge;
        }
        case ISK.noprofile: {
            return AttrKind_.NoProfile;
        }
        case ISK.norecurse: {
            return AttrKind_.NoRecurse;
        }
        case ISK.noredzone: {
            return AttrKind_.NoRedZone;
        }
        case ISK.noreturn: {
            return AttrKind_.NoReturn;
        }
        case ISK.nosanitize_coverage: {
            return AttrKind_.NoSanitizeCoverage;
        }
        case ISK.nosync: {
            return AttrKind_.NoSync;
        }
        case ISK.noundef: {
            return AttrKind_.NoUndef;
        }
        case ISK.nounwind: {
            return AttrKind_.NoUnwind;
        }
        case ISK.nonlazybind: {
            return AttrKind_.NonLazyBind;
        }
        case ISK.nonnull: {
            return AttrKind_.NonNull;
        }
        case ISK.null_pointer_is_valid: {
            return AttrKind_.NullPointerIsValid;
        }
        case ISK.optforfuzzing: {
            return AttrKind_.OptForFuzzing;
        }
        case ISK.optsize: {
            return AttrKind_.OptimizeForSize;
        }
        case ISK.optnone: {
            return AttrKind_.OptimizeNone;
        }
        case ISK.readnone: {
            return AttrKind_.ReadNone;
        }
        case ISK.readonly: {
            return AttrKind_.ReadOnly;
        }
        case ISK.returned: {
            return AttrKind_.Returned;
        }
        case ISK.returns_twice: {
            return AttrKind_.ReturnsTwice;
        }
        case ISK.signext: {
            return AttrKind_.SExt;
        }
        case ISK.safestack: {
            return AttrKind_.SafeStack;
        }
        case ISK.sanitize_address: {
            return AttrKind_.SanitizeAddress;
        }
        case ISK.sanitize_hwaddress: {
            return AttrKind_.SanitizeHWAddress;
        }
        case ISK.sanitize_memtag: {
            return AttrKind_.SanitizeMemTag;
        }
        case ISK.sanitize_memory: {
            return AttrKind_.SanitizeMemory;
        }
        case ISK.sanitize_thread: {
            return AttrKind_.SanitizeThread;
        }
        case ISK.shadowcallstack: {
            return AttrKind_.ShadowCallStack;
        }
        case ISK.speculatable: {
            return AttrKind_.Speculatable;
        }
        case ISK.speculative_load_hardening: {
            return AttrKind_.SpeculativeLoadHardening;
        }
        case ISK.ssp: {
            return AttrKind_.StackProtect;
        }
        case ISK.sspreq: {
            return AttrKind_.StackProtectReq;
        }
        case ISK.sspstrong: {
            return AttrKind_.StackProtectStrong;
        }
        case ISK.strictfp: {
            return AttrKind_.StrictFP;
        }
        case ISK.swiftasync: {
            return AttrKind_.SwiftAsync;
        }
        case ISK.swifterror: {
            return AttrKind_.SwiftError;
        }
        case ISK.swiftself: {
            return AttrKind_.SwiftSelf;
        }
        case ISK.uwtable: {
            return AttrKind_.UWTable;
        }
        case ISK.willreturn: {
            return AttrKind_.WillReturn;
        }
        case ISK.writeonly: {
            return AttrKind_.WriteOnly;
        }
        case ISK.zeroext: {
            return AttrKind_.ZExt;
        }
        case ISK.byref: {
            return AttrKind_.ByRef;
        }
        case ISK.byval: {
            return AttrKind_.ByVal;
        }
        case ISK.elementtype: {
            return AttrKind_.ElementType;
        }
        case ISK.inalloca: {
            return AttrKind_.InAlloca;
        }
        case ISK.preallocated: {
            return AttrKind_.Preallocated;
        }
        case ISK.sret: {
            return AttrKind_.StructRet;
        }
        case ISK.align_: {
            return AttrKind_.Alignment;
        }
        case ISK.allocsize: {
            return AttrKind_.AllocSize;
        }
        case ISK.dereferenceable: {
            return AttrKind_.Dereferenceable;
        }
        case ISK.dereferenceable_or_null: {
            return AttrKind_.DereferenceableOrNull;
        }
        case ISK.alignstack: {
            return AttrKind_.StackAlignment;
        }
        case ISK.vscale_range: {
            return AttrKind_.VScaleRange;
        }
        default: break;
    }
    return AttrKind_.None;
}
// HTWX
void 检查初始化() {
    .factory = new IR工厂_(节点工厂标志_.合成工厂_, 节点标志_.合成的_);
    dstring[] mds = ["dbg"d, "tbaa"d, "prof"d, "fpmath"d,
        "range"d, "tbaa.struct"d, "invariant.load"d, "alias.scope"d,
        "noalias"d, "nontemporal"d, "llvm.mem.parallel_loop_access"d,
        "nonnull"d, "dereferenceable"d, "dereferenceable_or_null"d,
        "make.implicit"d, "unpredictable"d, "invariant.group"d,
        "align"d, "llvm.loop"d, "type"d, "section_prefix"d, "absolute_symbol"d,
        "associated"d, "callees"d, "irr_loop"d, "llvm.access.group"d, "callback"d,
        "llvm.preserve.access.index"d, "vcall_visibility"d, "noundef"d, "annotation"d];
    {
        for (int i = 0; i < mds.length; ++i) {
            dstring s = mds[i];
            .getMDKindID(s);
        }
    }
    .amalgamatedDuplicates = 返回零值!(词典_!(DuplicateInfoForFiles))();
    .TheTrueVal = CGet_.s·CInt_getTrue();
    .TheFalseVal = CGet_.s·CInt_getFalse();
}
void 源文件初始检查(基础节点.源文件_ file) {
    if (file.目标种类 != ISK.源文件) {
        return;
    }
    源文件_ sou = (cast(源文件_)(file));
}
检查源文件函数_ 创建IR检查(程序主机接口_ 主机, bool 诊断, 诊断收集_ _诊断集) {
    .报告错误 = 诊断;
    .诊断集 = _诊断集;
    .当前主机 = 主机;
    .当前编译选项 = (cast(编译选项_)(当前主机.获取编译选项()));
    // 目标平台 = 当前编译选项.目标平台!;
    return cast(检查源文件函数_)(·fd(&.检查源文件入口));
}
void 检查源文件入口(基础节点.源文件_ sou) {
    if (sou.种类 == SK.源文件) {
        .当前源文件 = (cast(源文件_)((cast(基础节点.源文件_)(sou))));
        .检查源文件(.当前源文件);
    }
    else {
        throw new Throwable(·to!(string)("不是klang源文件_"d));
    }
}
void 检查源文件(源文件_ sou) {
    循环每个!(基础节点.节点_, void*)(sou.语句组, (基础节点.节点_ v, size_t i) {
        .检查每个元素(v, i);
        return null;
    });
}
void 检查每个元素(基础节点.节点_ n, size_t _) {
    .检查源文件元素(n);
}
类型_ 解析类型成员组(类型_ 类型) {
    if (!类型.成员已解析) {
        if (类型.种类 == TypeID_.StructTyID) {
            基础符号_ 符号 = 类型.符号;
            if ((符号 !is ··null!(基础符号_)) && (符号.标志 & 符号标志_.结构字面量_) != 0) {
                结构类型节点_ 结构节点 = (cast(结构类型节点_)(符号.声明组[0]));
                if ((结构节点.类型组 !is null) && (结构节点.类型组.原型 !is ··null!(节点_[]))) {
                    类型_[] 成员组 = 映射!(节点_, 类型_)(结构节点.类型组, (节点_ t, size_t _) { return .获取类型节点的类型(t); });
                    (cast(结构类型_)(类型)).ContainedTys = 成员组;
                    (cast(结构类型_)(类型)).是不透明的 = false;
                }
            }
        }
        类型.成员已解析 = true;
    }
    return 类型;
}
类型_ 获取类型节点的类型(节点_ n) {
    switch (n.目标种类) {
        case ISK.ptr: {
            不透明指针类型_ pn = (cast(不透明指针类型_)(n));
            if (pn !is ··null!(不透明指针类型_)) {
                地址空间设置_ 地址空间设置 = (cast(地址空间设置_)(pn.地址空间));
                IR数字字面量_ 值 = (cast(IR数字字面量_)(地址空间设置.值));
                return .getUnqualTy((cast(uint)(值.整数值)));
            }
            else {
                return .getUnqualTy(0);
            }
        }
        case ISK.void_: {
            return .VoidTy;
        }
        case ISK.half: {
            return .HalfTy;
        }
        case ISK.bfloat: {
            return .BFloatTy;
        }
        case ISK.float_: {
            return .FloatTy;
        }
        case ISK.double_: {
            return .DoubleTy;
        }
        case ISK.x86_fp80: {
            return .X86_FP80Ty;
        }
        case ISK.fp128: {
            return .FP128Ty;
        }
        case ISK.ppc_fp128: {
            return .PPC_FP128Ty;
        }
        case ISK.label: {
            return .LabelTy;
        }
        case ISK.metadata: {
            return .MetadataTy;
        }
        case ISK.x86_mmx: {
            return .X86_MMXTy;
        }
        case ISK.x86_amx: {
            return .X86_AMXTy;
        }
        case ISK.token: {
            return .TokenTy;
        }
        case ISK.opaque: {
            return TGet_.s·STy_get(返回零值!(符号_)());
        }
        case ISK.整数类型: {
            整数类型节点_ tn = (cast(整数类型节点_)(n));
            IR数字字面量_ num = (cast(IR数字字面量_)(tn.大小));
            return TGet_.s·IntTy_get((cast(uint)(num.整数值)));
        }
        case ISK.结构类型: {
            结构类型节点_ tn = (cast(结构类型节点_)(n));
            return TGet_.s·STy_get((cast(符号_)(tn.符号)), tn.是压缩的);
        }
        case ISK.向量类型: {
            向量类型节点_ tn = (cast(向量类型节点_)(n));
            return TGet_.s·VTy_get(.获取类型节点的类型(tn.类型), tn.是可扩展的, (cast(uint)(tn.数量.整数值)));
        }
        case ISK.数组类型: {
            数组类型节点_ tn = (cast(数组类型节点_)(n));
            return TGet_.s·ArrTy_get(.获取类型节点的类型(tn.类型), tn.数量.整数值);
        }
        case ISK.指针类型: {
            指针类型节点_ tn = (cast(指针类型节点_)(n));
            uint 地址 = tn.地址空间 ? (cast(uint)((cast(IR数字字面量_)(tn.地址空间.值)).整数值)) : 0;
            return TGet_.s·PtrTy_get(.获取类型节点的类型(tn.类型), 地址);
        }
        case ISK.函数类型: {
            函数类型节点_ tn = (cast(函数类型节点_)(n));
            类型_ 返回类型 = .获取类型节点的类型(tn.返回类型);
            类型_[] 参数组 = 映射定义的!(节点_, 类型_)(tn.形参组, (节点_ a, size_t _) {
                if (a.目标种类 == ISK.形参声明) {
                    return .获取形参声明的类型(a);
                }
                return ··null!(类型_);
            });
            return TGet_.s·FuncTy_get(返回类型, 参数组, tn.IsVarArg);
        }
        case ISK.类型引用: {
            类型引用_ tn = (cast(类型引用_)(n));
            return .获取类型引用的类型(tn);
        }
        default: break;
    }
    .错误(n, 诊断集_.未知类型_错误);
    return .未知类型;
}
符号_ 获取类型引用的解析符号(类型引用_ tn) {
    Value links = .获取节点解析值!(Value)(tn);
    if (links.解析符号 !is ··null!(符号_)) {
        return links.解析符号;
    }
    dstring 名称 = tn.类型名.内容;
    符号_ 符号 = .解析名称(tn, 名称, 符号标志_.类型_, tn.类型名, 诊断集_.未发现符号_0, true);
    links.解析符号 = 符号;
    return links.解析符号;
}
符号_ 解析特性引用符号(··IR节点_.IR标识符_ n) {
    Value links = .获取节点解析值!(Value)(n);
    if (links.解析符号 !is ··null!(符号_)) {
        return links.解析符号;
    }
    dstring 名称 = n.内容;
    符号_ 符号 = .解析名称(n, 名称, 符号标志_.特性声明_, n, 诊断集_.未发现符号_0, true);
    links.解析符号 = 符号;
    return links.解析符号;
}
符号_ 解析函数封装引用符号(封装设置_ n, dstring 名称) {
    Value links = .获取节点解析值!(Value)(n);
    if (links.解析符号 !is ··null!(符号_)) {
        return links.解析符号;
    }
    节点_ errN = n.值 ? n.值 : n;
    符号_ 符号 = .解析名称(n, 名称, 符号标志_.封装声明_, errN, 诊断集_.未发现符号_0, true);
    links.解析符号 = 符号;
    return links.解析符号;
}
符号_ 解析值引用符号(··IR节点_.IR标识符_ n, dstring 名称) {
    Value links = .获取节点解析值!(Value)(n);
    if (links.解析符号 !is ··null!(符号_)) {
        return links.解析符号;
    }
    符号_ 符号 = .解析名称(n, 名称, 符号标志_.全局或局部值_, n, 诊断集_.未发现符号_0, true);
    links.解析符号 = 符号;
    return links.解析符号;
}
类型_ 获取类型引用的类型(类型引用_ tn) {
    符号_ 符号 = .获取类型引用的解析符号(tn);
    return .获取符号的声明类型(符号);
}
类型_ 获取符号的类型(基础符号_ s) {
    if (s is ··null!(基础符号_)) {
        return .未知类型;
    }
    符号_ 符号 = (cast(符号_)(s));
    return 符号.类型;
}
类型_ 获取符号的声明类型(基础符号_ s = ··null!(基础符号_)) {
    if (s is ··null!(基础符号_)) {
        return .未知类型;
    }
    符号_ 符号 = (cast(符号_)(s));
    assert((符号.标志 & 符号标志_.类型声明_) != 0, "不是类型声明符号"c);
    return .获取类型声明的声明类型(符号);
}
类型_ 获取类型声明的声明类型(符号_ 符号) {
    if (符号.声明类型 !is ··null!(类型_)) {
        return 符号.声明类型;
    }
    基础节点.节点_ 声明 = 符号.值声明;
    节点_ tn = (cast(类型声明_)(声明)).类型;
    if (tn.目标种类 == ISK.结构类型 || tn.目标种类 == ISK.opaque) {
        符号.声明类型 = .获取类型节点的类型(tn);
    }
    else {
        if (!.加入类型决议(符号, 类型系统名称_.声明类型_)) {
            符号.声明类型 = .未知类型;
            return .未知类型;
        }
        类型_ t = .获取类型节点的类型(tn);
        if (!.弹出类型决议()) {
            符号.声明类型 = .未知类型;
            .错误(声明, 诊断集_.非结构类型正向引用错误);
            return .未知类型;
        }
        符号.声明类型 = t;
    }
    return 符号.声明类型;
}
类型_ 获取形参声明的类型(节点_ arg) {
    if (arg.目标种类 == ISK.三点号) {
        return ··null!(类型_);
    }
    形参声明_ n = (cast(形参声明_)(arg));
    return .获取类型节点的类型(n.类型);
}
void 检查用户历史数据(用户历史数据_ n) {
}
void 检查源文件元素(基础节点.节点_ 节点 = ··null!(基础节点.节点_)) {
    if (节点 is ··null!(基础节点.节点_)) {
        return;
    }
    if (!是IR节点(节点)) {
        return;
    }
    if ((节点.标志 & 节点标志_.完成检查_) != 0) {
        return;
    }
    节点.标志 |= (cast(整数_)(节点标志_.完成检查_));
    节点_ n = (cast(节点_)(节点));
    long k = n.目标种类;
    switch (k) {
        case ISK.平台设置: {
            .检查平台设置((cast(平台设置_)(n)));
            break;
        }
        case ISK.数据布局设置: {
            .检查数据布局设置((cast(数据布局设置_)(n)));
            break;
        }
        case ISK.目标语句: {
            .检查目标语句((cast(目标语句_)(n)));
            break;
        }
        case ISK.类型声明: {
            .检查类型声明((cast(类型声明_)(n)));
            break;
        }
        case ISK.函数定义: {
            .检查函数定义((cast(函数定义_)(n)));
            break;
        }
        case ISK.函数声明: {
            .检查函数声明((cast(函数声明_)(n)));
            break;
        }
        case ISK.函数体: {
            .检查函数体((cast(函数体_)(n)));
            break;
        }
        case ISK.用户历史数据: {
            .检查用户历史数据((cast(用户历史数据_)(n)));
            break;
        }
        case ISK.全局变量声明: {
            .检查全局变量声明((cast(全局变量声明_)(n)));
            break;
        }
        case ISK.别名声明: {
            .检查别名声明((cast(别名声明_)(n)));
            break;
        }
        case ISK.封装声明: {
            .检查封装声明((cast(封装声明_)(n)));
            break;
        }
        case ISK.独立元数据: {
            .检查独立元数据((cast(独立元数据_)(n)));
            break;
        }
        case ISK.元数据声明: {
            .检查元数据声明((cast(元数据声明_)(n)));
            break;
        }
        case ISK.特性声明: {
            .检查特性声明((cast(特性声明_)(n)));
            break;
        }
        case ISK.全局摘要声明: {
            .检查全局摘要声明((cast(全局摘要声明_)(n)));
            break;
        }
        case ISK.模块级汇编: {
            .检查模块级汇编((cast(模块级汇编_)(n)));
            break;
        }
        case ISK.形参声明: {
            .检查形参声明((cast(形参声明_)(n)));
            break;
        }
        case ISK.局部变量声明: {
            .检查局部变量声明((cast(局部变量声明_)(n)));
            break;
        }
        case ISK.块声明: {
            .检查块声明((cast(块声明_)(n)));
            break;
        }
        case ISK.结构类型: {
            .检查结构字面量类型((cast(结构类型节点_)(n)));
            break;
        }
        case ISK.数组类型: {
            .检查数组字面量类型((cast(数组类型节点_)(n)));
            break;
        }
        case ISK.向量类型: {
            .检查向量字面量类型((cast(向量类型节点_)(n)));
            break;
        }
        case ISK.全局表达式: {
            .检查全局表达式((cast(全局表达式_)(n)));
            break;
        }
        case ISK.值表达式: {
            .检查值表达式((cast(值表达式_)(n)));
            break;
        }
        case ISK.对齐设置: {
            .检查对齐设置((cast(对齐设置_)(n)));
            break;
        }
        case ISK.地址空间设置: {
            .检查地址空间设置((cast(地址空间设置_)(n)));
            break;
        }
        case ISK.同步范围设置: {
            .检查同步范围设置((cast(同步范围设置_)(n)));
            break;
        }
        case ISK.操作数标签组: {
            .检查操作数标签组((cast(操作数标签组_)(n)));
            break;
        }
        case ISK.实参表达式: {
            .检查实参表达式((cast(实参表达式_)(n)));
            break;
        }
        case ISK.不及指令:
        case ISK.返回指令:
        case ISK.跳转指令:
        case ISK.假如指令:
        case ISK.直接跳转指令:
        case ISK.唤出指令:
        case ISK.重启指令:
        case ISK.清理返回指令:
        case ISK.清理场指令:
        case ISK.捕获返回指令:
        case ISK.捕获场指令:
        case ISK.捕获分支指令:
        case ISK.调用跳转指令:
        case ISK.取反指令:
        case ISK.整数和差积及左移指令:
        case ISK.小数和差积及左移指令:
        case ISK.有无符号求商及右移指令:
        case ISK.有无符号求余数运算指令:
        case ISK.位运算指令:
        case ISK.比较运算指令:
        case ISK.转换类指令:
        case ISK.可变参数指令:
        case ISK.提取元素指令:
        case ISK.插入元素指令:
        case ISK.洗牌向量指令:
        case ISK.分配指令:
        case ISK.储存指令:
        case ISK.加载指令:
        case ISK.着陆场指令:
        case ISK.冻结指令:
        case ISK.调用指令:
        case ISK.原子修改内存按条件指令:
        case ISK.原子修改内存指令:
        case ISK.栅格指令:
        case ISK.获取元素指针指令:
        case ISK.提取值指令:
        case ISK.插入值指令: {
            .检查指令语句(n);
            break;
        }
        default: break;
    }
    return;
}
void 检查操作数标签组(操作数标签组_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    循环每个!(··IR节点_.操作数标签_, void*)(n.标签组, (··IR节点_.操作数标签_ v, size_t i) {
        .检查每个元素(v, i);
        return null;
    });
    BundleDef[] bs = 创建数组!(BundleDef)();
    foreach (··IR节点_.操作数标签_ bn; n.标签组) {
        .检查源文件元素(bn);
        BundleDef b = .有解析值!(BundleDef)(bn);
        .追加!(BundleDef)(bs, b);
    }
    .设置解析值(n, new BundleDefS(bs));
}
void 检查同步范围设置(同步范围设置_ n) {
    ubyte delegate() 获取值;
    dstring 值;
    ubyte ssid;
    同步值_ V;
    ubyte 获取值·func() {
        ubyte NewSSID;
        if (SSC.具有(值)) {
            return SSC.获取(值);
        }
        NewSSID = (cast(ubyte)(SSC.大小() + 1));
        SSC.p·设置(值, NewSSID);
        return SSC.获取(值);
    }
    获取值 = &获取值·func;
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    值 = (cast(IR文本字面量_)(n.值)).内容;
    ssid = 获取值();
    V = new 同步值_(ssid);
    .设置解析值(n, V);
}
void 检查对齐设置(对齐设置_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    ulong 值 = (cast(IR数字字面量_)(n.值)).整数值;
    if (!isPowerOf2_64(值)) {
        .错误(n.值, 诊断集_.整数溢出);
    }
    if (值 > ((cast(ulong)(1)) << 32)) {
        .错误(n.值, 诊断集_.整数溢出);
    }
    对齐值_ V = new 对齐值_(值);
    .设置解析值(n, V);
}
void 检查地址空间设置(地址空间设置_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    uint 值 = (cast(uint)((cast(IR数字字面量_)(n.值)).整数值));
    if (值 != (cast(IR数字字面量_)(n.值)).整数值) {
        .错误(n.值, 诊断集_.整数溢出);
    }
    地址值_ V = new 地址值_(值);
    .设置解析值(n, V);
}
void 检查值表达式(值表达式_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查表达式(n.值, n.类型);
    Value V = .有解析值!(Value)(n.值);
    if (V is ··null!(Value)) {
        .错误(n.值, 诊断集_.未定义的值);
    }
    else {
        .设置解析值(n, V);
    }
}
void 检查数据布局设置(数据布局设置_ n) {
    节点_ V = n.值;
    assert((V !is ··null!(节点_)) && V.目标种类 == ISK.文本字面量, "设置错误"c);
    dstring 内容 = (cast(IR文本字面量_)(V)).内容;
    DataLayout 布局 = new DataLayout();
    bool 有错误 = parseSpecifier(布局, 内容);
    if (有错误) {
        .错误(n.值, 诊断集_.不支持的数据布局或布局语法有错误);
    }
    .当前布局 = 布局;
}
void 检查平台设置(平台设置_ n) {
    节点_ V = n.值;
    assert((V !is ··null!(节点_)) && V.目标种类 == ISK.文本字面量, "设置错误"c);
    dstring 内容 = (cast(IR文本字面量_)(V)).内容;
    Triple T = 编译目标平台内容(内容);
    .目标平台 = T;
}
void 检查目标语句(目标语句_ n) {
    节点_ V = n.值;
    .检查源文件元素(V);
}
void 检查类型声明(类型声明_ n) {
    .检查源文件元素(n.类型);
    .获取类型声明的声明类型((cast(符号_)(n.符号)));
}
void 检查结构字面量类型(结构类型节点_ n) {
    基础节点.节点数组_!(节点_) 类型组 = n.类型组;
    if ((类型组 !is null) && (类型组.原型 !is ··null!(节点_[])) && 类型组.length > 0) {
        {
            for (int i = 0; i < 类型组.length; ++i) {
                节点_ tn = 类型组[i];
                类型_ t = .获取类型节点的类型(tn);
                if (!.是结构体类型的有效成员类型(t)) {
                    .错误(tn, 诊断集_.a0_不是_1_2_的有效成员, 获取节点的文本(tn), "结构"d, "类型"d);
                }
            }
        }
    }
}
void 检查数组字面量类型(数组类型节点_ n) {
    节点_ tn = n.类型;
    类型_ t = .获取类型节点的类型(tn);
    if (!.是数组类型的有效成员类型(t)) {
        .错误(tn, 诊断集_.a0_不是_1_2_的有效成员, 获取节点的文本(tn), "数组"d, "类型"d);
    }
}
void 检查向量字面量类型(向量类型节点_ n) {
    节点_ tn = n.类型;
    类型_ t = .获取类型节点的类型(tn);
    if (!.是向量类型的有效成员类型(t)) {
        .错误(tn, 诊断集_.a0_不是_1_2_的有效成员, 获取节点的文本(tn), "向量"d, "类型"d);
    }
}
bool 是可扩展的向量类型(类型_ t) {
    return t.种类 == TypeID_.ScalableVectorTyID;
}
bool 是浮点类的类型(类型_ t) {
    return t.种类 == TypeID_.HalfTyID || t.种类 == TypeID_.BFloatTyID || t.种类 == TypeID_.FloatTyID || t.种类 == TypeID_.DoubleTyID || t.种类 == TypeID_.X86_FP80TyID || t.种类 == TypeID_.FP128TyID || t.种类 == TypeID_.PPC_FP128TyID;
}
bool 是向量类型的有效成员类型(类型_ t) {
    return t.种类 == TypeID_.IntegerTyID || t.种类 == TypeID_.PointerTyID || .是浮点类的类型(t);
}
bool 是数组类型的有效成员类型(类型_ t) {
    return t != .VoidTy && t != .LabelTy && t != .MetadataTy && t != .TokenTy && t != .X86_AMXTy && t.种类 != TypeID_.FunctionTyID && !.是可扩展的向量类型(t);
}
bool 是结构体类型的有效成员类型(类型_ t) {
    return t != .VoidTy && t != .LabelTy && t != .MetadataTy && t != .TokenTy && t.种类 != TypeID_.FunctionTyID;
}
LinkageTypes 检查链接特性(节点_ n) {
    LinkageTypes link = LinkageTypes.无效值_;
    bool 是定义 = n.目标种类 == ISK.函数定义;
    if (是定义 || n.目标种类 == ISK.函数声明) {
        全局声明_ fn = (cast(全局声明_)(n));
        link = 获取连接类型(fn.连接特性);
        if (link == LinkageTypes.无效值_) {
            link = LinkageTypes.ExternalLinkage;
        }
        switch (link) {
            case LinkageTypes.ExternalLinkage: {
                break;
            } // always ok.
            case LinkageTypes.ExternalWeakLinkage: {
                if (是定义) {
                    .错误(n, 诊断集_.a0_的_1_2_, "函数定义"d, "无效链接特性"d, "extern_weak"d);
                }
                break;
            }
            case LinkageTypes.PrivateLinkage:
            case LinkageTypes.InternalLinkage:
            case LinkageTypes.AvailableExternallyLinkage:
            case LinkageTypes.LinkOnceAnyLinkage:
            case LinkageTypes.LinkOnceODRLinkage:
            case LinkageTypes.WeakAnyLinkage:
            case LinkageTypes.WeakODRLinkage: {
                if (!是定义) {
                    .错误(n, 诊断集_.a0_的_1_2_, "函数声明"d, "无效链接特性"d, 获取ISK关键字文本(获取链接特性的令牌(link)));
                }
                break;
            }
            case LinkageTypes.AppendingLinkage:
            case LinkageTypes.CommonLinkage: {
                .错误(n, 诊断集_.a0_的_1_2_, "函数"d, "无效链接特性"d, 获取ISK关键字文本(获取链接特性的令牌(link)));
                break;
            }
            default: break;
        }
    }
    return link;
}
bool 检查运行时抢占(节点_ n) {
    bool DSOLocal = false;
    全局声明_ fn = (cast(全局声明_)(n));
    if ((fn !is ··null!(全局声明_)) && (fn.运行时抢占 !is ··null!(节点_))) {
        DSOLocal = fn.运行时抢占.目标种类 == ISK.dso_local;
    }
    return DSOLocal;
}
VisibilityTypes 检查可见性(节点_ n) {
    VisibilityTypes Visibility = VisibilityTypes.DefaultVisibility;
    全局声明_ fn = (cast(全局声明_)(n));
    if ((fn !is ··null!(全局声明_)) && (fn.可见性 !is ··null!(节点_))) {
        switch (fn.可见性.目标种类) {
            case ISK.default_: {
                Visibility = VisibilityTypes.DefaultVisibility;
                break;
            }
            case ISK.hidden: {
                Visibility = VisibilityTypes.HiddenVisibility;
                break;
            }
            case ISK.protected_: {
                Visibility = VisibilityTypes.ProtectedVisibility;
                break;
            }
            default: {
                Visibility = VisibilityTypes.DefaultVisibility;
                break;
            }
        }
    }
    return Visibility;
}
DLLStorageClassTypes 检查DLL储存类(节点_ n) {
    DLLStorageClassTypes DLLStorageClass = DLLStorageClassTypes.DefaultStorageClass;
    全局声明_ fn = (cast(全局声明_)(n));
    if ((fn !is ··null!(全局声明_)) && (fn.DLL储存类 !is ··null!(节点_))) {
        switch (fn.DLL储存类.目标种类) {
            case ISK.dllimport: {
                DLLStorageClass = DLLStorageClassTypes.DLLImportStorageClass;
                break;
            }
            case ISK.dllexport: {
                DLLStorageClass = DLLStorageClassTypes.DLLExportStorageClass;
                break;
            }
            default: {
                DLLStorageClass = DLLStorageClassTypes.DefaultStorageClass;
                break;
            }
        }
    }
    return DLLStorageClass;
}
bool isValidVisibilityForLinkage(VisibilityTypes V, LinkageTypes L) {
    return !.isLocalLinkage(L) || V == VisibilityTypes.DefaultVisibility;
}
bool isLocalLinkage(LinkageTypes L) {
    return L == LinkageTypes.InternalLinkage || L == LinkageTypes.PrivateLinkage;
}
bool isFirstClassType(类型_ Ty) {
    return Ty.种类 != TypeID_.FunctionTyID && Ty.种类 != TypeID_.VoidTyID;
}
bool isValidArgumentType(类型_ Ty) {
    return .isFirstClassType(Ty);
}
bool isVoidType(类型_ Ty) {
    return Ty.种类 == TypeID_.VoidTyID;
}
bool isArrayType(类型_ Ty) {
    return Ty.种类 == TypeID_.ArrayTyID;
}
bool 是函数类型的有效返回类型(类型_ t) {
    return t.种类 != TypeID_.FunctionTyID && t.种类 != TypeID_.LabelTyID && t.种类 != TypeID_.MetadataTyID;
}
AttrKind_ 获取需要类型特性键(long isk) {
    switch (isk) {
        case ISK.按引用设置: {
            return AttrKind_.ByRef;
        }
        case ISK.结构引用设置: {
            return AttrKind_.StructRet;
        }
        case ISK.预分配设置: {
            return AttrKind_.Preallocated;
        }
        case ISK.在内部分配设置: {
            return AttrKind_.InAlloca;
        }
        case ISK.按值设置: {
            return AttrKind_.ByVal;
        }
        default: break;
    }
    return AttrKind_.None;
}
AttrKind_ 获取整数值特性键(long isk) {
    switch (isk) {
        case ISK.对齐设置: {
            return AttrKind_.Alignment;
        }
        case ISK.分配大小设置: {
            return AttrKind_.AllocSize;
        }
        case ISK.不可引用的设置: {
            return AttrKind_.Dereferenceable;
        }
        case ISK.不可引用的或空设置: {
            return AttrKind_.DereferenceableOrNull;
        }
        case ISK.对齐堆栈设置: {
            return AttrKind_.StackAlignment;
        }
        case ISK.倍数范围设置: {
            return AttrKind_.VScaleRange;
        }
        default: break;
    }
    return AttrKind_.None;
}
特性组_ 设置特性到特性组(特性组_ t, 特性_ attr = ··null!(特性_)) {
    if (attr is ··null!(特性_)) {
        return t;
    }
    特性种类_ 特性种类 = attr.特性种类;
    switch (特性种类) {
        case 特性种类_.枚举特性_: {
            AttrKind_ 值 = (cast(枚举特性_)(attr)).值;
            t.枚举特性[值 / 8] |= (cast(ubyte)(1 << (值 % 8)));
            break;
        }
        case 特性种类_.整数特性_: {
            if (t.整数特性 is ··null!(整数特性_[])) {
                t.整数特性 = 创建数组!(整数特性_)();
            }
            AttrKind_ 键值 = (cast(整数特性_)(attr)).键;
            t.枚举特性[键值 / 8] |= (cast(ubyte)(1 << (键值 % 8)));
            int index = 键值 - AttrKind_.FirstIntAttr;
            t.整数特性[index] = (cast(整数特性_)(attr));
            break;
        }
        case 特性种类_.对齐特性_: {
            if (t.对齐特性 is ··null!(对齐特性_[])) {
                t.对齐特性 = 创建数组!(对齐特性_)();
            }
            AttrKind_ 键值 = (cast(对齐特性_)(attr)).键;
            t.枚举特性[键值 / 8] |= (cast(ubyte)(1 << (键值 % 8)));
            int index = 键值 - AttrKind_.FirstIntAttr;
            t.对齐特性[index] = (cast(对齐特性_)(attr));
            break;
        }
        case 特性种类_.文本特性_: {
            if ((t.文本特性 is null) || (t.文本特性.原型 is ··null!(文本特性_[dstring]))) {
                t.文本特性 = new 词典_!(文本特性_)();
            }
            dstring 键 = (cast(文本特性_)(attr)).键;
            t.文本特性.p·设置(键, (cast(文本特性_)(attr)));
            break;
        }
        case 特性种类_.类型特性_: {
            if (t.类型特性 is ··null!(类型特性_[])) {
                t.类型特性 = 创建数组!(类型特性_)();
            }
            AttrKind_ 键值 = (cast(类型特性_)(attr)).键;
            t.枚举特性[键值 / 8] |= (cast(ubyte)(1 << (键值 % 8)));
            int index = 键值 - AttrKind_.FirstTypeAttr;
            t.类型特性[index] = (cast(类型特性_)(attr));
            break;
        }
        default: break;
    }
    return t;
}
特性组_ 合并特性组(特性组_ t, 特性组_ s = ··null!(特性组_)) {
    void delegate(特性_[]) 合并特性数组到特性组;
    void delegate(词典_!(文本特性_)) 合并特性到特性词典;
    void 合并特性数组到特性组·func(特性_[] s = ··null!(特性_[])) {
        if ((s is ··null!(特性_[])) || s.length == 0) {
            return;
        }
        foreach (特性_ a; s) {
            t = .设置特性到特性组(t, a);
        }
        return;
    }
    合并特性数组到特性组 = &合并特性数组到特性组·func;
    void 合并特性到特性词典·func(词典_!(文本特性_) s = ··null!(词典_!(文本特性_))) {
        if ((s is null) || (s.原型 is ··null!(文本特性_[dstring])) || s.大小() == 0) {
            return;
        }
        s.p·循环每个((文本特性_ ss, dstring k) {
            t.文本特性.p·设置(k, ss);
        });
        return;
    }
    合并特性到特性词典 = &合并特性到特性词典·func;
    if (s is ··null!(特性组_)) {
        return t;
    }
    合并特性数组到特性组((cast(特性_[])(s.整数特性)));
    合并特性到特性词典(s.文本特性);
    合并特性数组到特性组((cast(特性_[])(s.对齐特性)));
    合并特性数组到特性组((cast(特性_[])(s.类型特性)));
    if (s.枚举特性 !is ··null!(ubyte[])) {
        {
            for (int i = 0; i < s.枚举特性.length; ++i) {
                t.枚举特性[i] |= s.枚举特性[i];
            }
        }
    }
    return t;
}
bool 函数具有函数特性(特性组_[] 特性组, AttrKind_ kind) {
    if (特性组.length < 1) {
        return false;
    }
    特性组_ 函数特性 = 特性组[0];
    if (函数特性 is ··null!(特性组_)) {
        return false;
    }
    int index = kind / 8;
    int L = 1 << (kind % 8);
    return (函数特性.枚举特性[index] & L) != 0;
}
bool 函数具有返回值特性(特性组_[] 特性组, AttrKind_ kind) {
    if (特性组.length < 2) {
        return false;
    }
    特性组_ 函数特性 = 特性组[1];
    if (函数特性 is ··null!(特性组_)) {
        return false;
    }
    int index = kind / 8;
    int L = 1 << (kind % 8);
    return (函数特性.枚举特性[index] & L) != 0;
}
bool 函数的参数具有特性(特性组_[] 特性组, long 参数号, AttrKind_ kind) {
    if (特性组.length < 参数号 + 3) {
        return false;
    }
    特性组_ 参数特性 = 特性组[参数号 + 2];
    if (参数特性 is ··null!(特性组_)) {
        return false;
    }
    int index = kind / 8;
    int L = 1 << (kind % 8);
    return (参数特性.枚举特性[index] & L) != 0;
}
特性组_ 获取特性引用的特性组(··IR节点_.IR标识符_ n) {
    符号_ s = .解析特性引用符号(n);
    if (s is ··null!(符号_)) {
        return ··null!(特性组_);
    }
    Value t = .获取符号声明值(s);
    assert(t.种类 == ValueTy_.特性组_, "不是特性组值"c);
    return (cast(特性组值_)(t)).特性组;
}
void 检查函数定义(函数定义_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    Function FV = .检查函数头(n);
    .检查源文件元素(n.函数体);
    BasicBlock[] BBs = (cast(BasicBlock[])(.有解析值!(Value)(n.函数体).Ops));
    if ((BBs !is ··null!(BasicBlock[])) && BBs.length > 0) {
        FV.BasicBlocks = new 词典_!(BasicBlock)();
    }
    foreach (BasicBlock b; BBs) {
        FV.BasicBlocks.p·设置(b.符号.名称, b);
    }
    .设置解析值(n, FV);
}
void 检查函数体(函数体_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    BasicBlock[] BBS = 创建数组!(BasicBlock)();
    foreach (节点_ b; n.基本块组) {
        .检查源文件元素(b);
        BasicBlock BB = .有解析值!(BasicBlock)(b);
        .追加!(BasicBlock)(cast(BasicBlock[])(BBS), BB);
    }
    函数体 F = new 函数体(BBS);
    .设置解析值(n, F);
}
void 检查块声明(块声明_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    Value[] 语句组 = 创建数组!(Value)();
    .检查源文件元素(n.name);
    foreach (节点_ I; n.语句组) {
        .检查源文件元素(I);
        .追加!(Value)(语句组, .有解析值!(Value)(I));
    }
    BasicBlock BB;
    if ((cast(符号_)(n.符号)).声明值 !is ··null!(Value)) {
        BB = (cast(BasicBlock)((cast(符号_)(n.符号)).声明值));
    }
    else {
        BB = new BasicBlock();
        (cast(符号_)(n.符号)).声明值 = BB;
        BB.符号 = n.符号;
        BB.类型 = .LabelTy;
    }
    BB.Ops = 语句组;
    .设置解析值(n, BB);
}
Function 检查函数头(函数基类_ n) {
    LinkageTypes Linkage = .检查链接特性(n);
    bool DSOLocal = .检查运行时抢占(n);
    VisibilityTypes Visibility = .检查可见性(n);
    DLLStorageClassTypes DLLStorageClass = .检查DLL储存类(n);
    if (DSOLocal && DLLStorageClass == DLLStorageClassTypes.DLLImportStorageClass) {
        .错误(n.DLL储存类, 诊断集_.a0_的_1_与_2_冲突, "函数"d, "dso_local"d, "dllimport"d);
    }
    if (!.isValidVisibilityForLinkage(Visibility, Linkage)) {
        节点_ err = n.可见性 ? n.可见性 : n.连接特性 ? n.连接特性 : n.name ? n.name : n;
        .错误(err, 诊断集_.symbol_with_local_linkage_must_have_default_visibility);
    }
    特性组_[] 特性组 = 创建数组!(特性组_)();
    特性组.length = n.参数列表.length + 2;
    特性组_ 函数特性 = .检查特性组(n.函数特性);
    特性组[0] = 函数特性;
    类型_ RetType = .获取类型节点的类型(n.返回类型);
    if (!.是函数类型的有效返回类型(RetType)) {
        .错误(n.返回类型, 诊断集_.invalid_function_return_type);
    }
    特性组_ 返回特性 = .检查特性组(n.返回类型特性);
    特性组[1] = 返回特性;
    循环每个!(节点_, void*)(n.参数列表, (节点_ v, size_t i) {
        .检查每个元素(v, i);
        return null;
    });
    类型_[] ParamTypeList = 创建数组!(类型_)();
    bool IsVarArg = n.IsVarArg ? true : false;
    {
        for (int i = 0; i < n.参数列表.length; ++i) {
            节点_ arg = n.参数列表[i];
            if (arg.目标种类 == ISK.形参声明) {
                Argument argV = .有解析值!(Argument)(arg);
                .追加!(类型_)(ParamTypeList, argV.类型);
                特性组_ 形参特性 = argV.特性组;
                if (形参特性 !is ··null!(特性组_)) {
                    特性组[i + 2] = 形参特性;
                }
            }
            else if (arg.目标种类 == ISK.三点号) {
                if (i != n.参数列表.length - 1) {
                    .错误(arg, 诊断集_.可变参数必须是最后一个参数);
                }
            }
        }
    }
    .检查源文件元素(n.未命名的地址);
    UnnamedAddr unnamedAddr = UnnamedAddr.None;
    if (n.未命名的地址 !is ··null!(节点_)) {
        if (n.未命名的地址.目标种类 == ISK.unnamed_addr) {
            unnamedAddr = UnnamedAddr.Global;
        }
        else if (n.未命名的地址.目标种类 == ISK.local_unnamed_addr) {
            unnamedAddr = UnnamedAddr.Local;
        }
        else {
            .错误(n.未命名的地址, 诊断集_.未知指令_0, 获取节点的文本(n));
        }
    }
    uint AddrSpace = 0;
    if (n.地址空间 !is ··null!(节点_)) {
        assert(n.地址空间.目标种类 == ISK.数字字面量, "地址空间设置错误"c);
        IR数字字面量_ 地址 = (cast(IR数字字面量_)(n.地址空间));
        uint 转为32位 = (cast(uint)(地址.整数值));
        if (转为32位 != 地址.整数值) {
        }
        AddrSpace = 转为32位;
    }
    函数类型_ FT = TGet_.s·FuncTy_get(RetType, ParamTypeList, IsVarArg);
    指针类型_ PFT = TGet_.s·PtrTy_get(FT, AddrSpace);
    if (!.isVoidType(RetType) && .函数的参数具有特性(特性组, 0, AttrKind_.StructRet)) {
        .错误(n.返回类型, 诊断集_.functions_with_sret_argument_must_return_void);
    }
    .检查源文件元素(n.对齐设置);
    Align_ Alignment = new Align_();
    if (n.对齐设置 !is ··null!(节点_)) {
        Alignment = .有解析值!(对齐值_)(n.对齐设置).Val;
    }
    dstring Section = ""d;
    if (n.段设置 !is ··null!(节点_)) {
        assert(n.段设置.目标种类 == ISK.文本字面量, "段设置错误"c);
        IR文本字面量_ 段 = (cast(IR文本字面量_)(n.段设置));
        Section = 段.内容;
    }
    dstring Partition = ""d;
    if (n.隔板设置 !is ··null!(节点_)) {
        assert(n.隔板设置.目标种类 == ISK.文本字面量, "隔板设置错误"c);
        IR文本字面量_ 隔板 = (cast(IR文本字面量_)(n.隔板设置));
        Partition = 隔板.内容;
    }
    封装值_ C;
    dstring 封装值 = ""d;
    if (n.函数封装 !is ··null!(节点_)) {
        封装设置_ 封装 = (cast(封装设置_)(n.函数封装));
        if (封装.值 !is ··null!(节点_)) {
            封装值 = (cast(IR文本字面量_)(封装.值)).内容;
        }
        else if (n.name !is ··null!(··IR节点_.IR标识符_)) {
            封装值 = n.name.内容;
        }
        else {
            .错误(n.函数封装, 诊断集_.a0_, "未知封装"d);
        }
        assert(封装值 !is ··null!(dstring), "封装值设置错误"c);
        符号_ s = .解析函数封装引用符号(封装, 封装值);
        if (s is ··null!(符号_)) {
            .错误(n.函数封装, 诊断集_.未定义的全局值);
        }
        else {
            Value t = .获取符号声明值(s);
            C = (cast(封装值_)(t));
        }
    }
    dstring GC = ""d;
    if (n.GC设置 !is ··null!(节点_)) {
        assert(n.GC设置.目标种类 == ISK.文本字面量, "GC设置错误"c);
        GC = (cast(IR文本字面量_)(n.GC设置)).内容;
    }
    Constant Prefix = 返回零值!(Constant)();
    if (n.前缀设置 !is ··null!(全局表达式_)) {
        .检查全局表达式(n.前缀设置);
        Constant P = .有解析值!(Constant)(n.前缀设置);
        Prefix = P;
    }
    Constant Prologue = 返回零值!(Constant)();
    if (n.序言设置 !is ··null!(全局表达式_)) {
        .检查全局表达式(n.序言设置);
        Constant P = .有解析值!(Constant)(n.序言设置);
        Prologue = P;
    }
    Constant PersonalityFn = 返回零值!(Constant)();
    if (n.个性设置 !is ··null!(全局表达式_)) {
        .检查全局表达式(n.个性设置);
        Constant P = .有解析值!(Constant)(n.个性设置);
        PersonalityFn = P;
    }
    Function 值 = new Function();
    值.符号 = (cast(符号_)(n.符号));
    值.Align = Alignment;
    值.Visibility = Visibility;
    值.特性组 = 特性组;
    值.ValueType = FT;
    值.类型 = TGet_.s·PtrTy_get(FT, AddrSpace);
    值.AddrSpace = AddrSpace;
    值.UnnamedAddrVal = unnamedAddr;
    值.Section = Section;
    值.ObjComdat = C;
    值.Partition = Partition;
    值.DllStorageClass = DLLStorageClass;
    if ((PersonalityFn !is ··null!(Constant)) || (Prefix !is ··null!(Constant)) || (Prologue !is ··null!(Constant))) {
        if (值.Ops is ··null!(Value[])) {
            值.Ops = 创建数组!(Value)();
            值.Ops.length = 3;
        }
        if (PersonalityFn !is ··null!(Constant)) {
            值.Ops[0] = PersonalityFn;
        }
        if (Prefix !is ··null!(Constant)) {
            值.Ops[1] = Prefix;
        }
        if (Prologue !is ··null!(Constant)) {
            值.Ops[2] = Prologue;
        }
    }
    if (GC !is ··null!(dstring)) {
        dstring id = ·to!(dstring)(值.toHash());
        GCNames.p·设置(id, GC);
        值.GC = GC;
    }
    return 值;
}
Value 获取特性声明特性组值(基础符号_ s) {
    符号_ 符号 = (cast(符号_)(s));
    if (符号.声明值 !is ··null!(Value)) {
        return 符号.声明值;
    }
    特性声明_ 声明 = (cast(特性声明_)(符号.值声明));
    基础节点.节点数组_!(节点_) 成员组 = 声明.成员;
    特性组_ attrs = new 特性组_();
    foreach (节点_ n; 成员组) {
        特性_ attr = .检查特性设置(n);
        .设置特性到特性组(attrs, attr);
    }
    符号.声明值 = new 特性组值_(attrs);
    return 符号.声明值;
}
Value 获取函数类声明的声明值(基础符号_ s) {
    符号_ 符号 = (cast(符号_)(s));
    if (符号.声明值 !is ··null!(Value)) {
        return 符号.声明值;
    }
    基础节点.节点_ 值声明 = s.值声明;
    .检查源文件元素(值声明);
    Value V = .有解析值!(Value)(值声明);
    符号.声明值 = V;
    return 符号.声明值;
}
Value 获取局部变量声明的声明值(基础符号_ s) {
    符号_ 符号 = (cast(符号_)(s));
    if (符号.声明值 !is ··null!(Value)) {
        return 符号.声明值;
    }
    局部变量声明_ 值声明 = (cast(局部变量声明_)(符号.值声明));
    .检查局部变量声明(值声明);
    Value V = .有解析值!(Value)(值声明);
    符号.声明值 = V;
    return 符号.声明值;
}
Value 获取全局变量声明的声明值(基础符号_ s) {
    符号_ 符号 = (cast(符号_)(s));
    if (符号.声明值 !is ··null!(Value)) {
        return 符号.声明值;
    }
    全局变量声明_ 值声明 = (cast(全局变量声明_)(符号.值声明));
    .检查全局变量声明(值声明);
    Value V = .有解析值!(Value)(值声明);
    符号.声明值 = V;
    return 符号.声明值;
}
Value 获取形参声明的声明值(基础符号_ s) {
    符号_ 符号 = (cast(符号_)(s));
    if (符号.声明值 !is ··null!(Value)) {
        return 符号.声明值;
    }
    形参声明_ 值声明 = (cast(形参声明_)(符号.值声明));
    .检查形参声明(值声明);
    Value V = .有解析值!(Value)(值声明);
    符号.声明值 = V;
    return 符号.声明值;
}
Value 获取别名声明的声明值(基础符号_ s) {
    符号_ 符号 = (cast(符号_)(s));
    if (符号.声明值 !is ··null!(Value)) {
        return 符号.声明值;
    }
    别名声明_ 值声明 = (cast(别名声明_)(符号.值声明));
    .检查别名声明(值声明);
    Value V = .有解析值!(Value)(值声明);
    符号.声明值 = V;
    return 符号.声明值;
}
Value 获取块声明的声明值(基础符号_ s) {
    符号_ 符号 = (cast(符号_)(s));
    if (符号.声明值 !is ··null!(Value)) {
        return 符号.声明值;
    }
    BasicBlock V = new BasicBlock(); // 有解析值(值声明)!;
    V.类型 = .LabelTy;
    V.符号 = 符号;
    符号.声明值 = V;
    return 符号.声明值;
}
Value 获取元数据声明的声明值(基础符号_ s) {
    符号_ 符号 = (cast(符号_)(s));
    if (符号.声明值 !is ··null!(Value)) {
        return 符号.声明值;
    }
    元数据值_ V = new 元数据值_(符号);
    符号.声明值 = V;
    return 符号.声明值;
}
Value 获取封装声明的封装值(基础符号_ s) {
    符号_ 符号 = (cast(符号_)(s));
    if (符号.声明值 !is ··null!(Value)) {
        return 符号.声明值;
    }
    封装声明_ 封装声明 = (cast(封装声明_)(符号.值声明));
    SelectionKind n = SelectionKind.Any;
    if (封装声明.值 !is ··null!(节点_)) {
        节点_ 值 = 封装声明.值;
        switch (值.目标种类) {
            case ISK.any: {
                n = SelectionKind.Any;
                break;
            }
            case ISK.exactmatch: {
                n = SelectionKind.ExactMatch;
                break;
            }
            case ISK.largest: {
                n = SelectionKind.Largest;
                break;
            }
            case ISK.noduplicates: {
                n = SelectionKind.NoDeduplicate;
                break;
            }
            case ISK.samesize: {
                n = SelectionKind.SameSize;
                break;
            }
            default: {
                n = SelectionKind.Any;
                break;
            }
        }
    }
    符号.声明值 = new 封装值_(n);
    return 符号.声明值;
}
Value 获取符号声明值(基础符号_ 符号) {
    if ((符号.标志 & 符号标志_.特性声明_) != 0) {
        return .获取特性声明特性组值(符号);
    }
    else if ((符号.标志 & 符号标志_.封装声明_) != 0) {
        return .获取封装声明的封装值(符号);
    }
    else if ((符号.标志 & (符号标志_.函数声明_ | 符号标志_.函数定义_)) != 0) {
        return .获取函数类声明的声明值(符号);
    }
    else if ((符号.标志 & 符号标志_.局部变量_) != 0) {
        return .获取局部变量声明的声明值(符号);
    }
    else if ((符号.标志 & 符号标志_.全局变量_) != 0) {
        return .获取全局变量声明的声明值(符号);
    }
    else if ((符号.标志 & 符号标志_.形参声明_) != 0) {
        return .获取形参声明的声明值(符号);
    }
    else if ((符号.标志 & 符号标志_.别名声明_) != 0) {
        return .获取别名声明的声明值(符号);
    }
    else if ((符号.标志 & 符号标志_.块声明_) != 0) {
        return .获取块声明的声明值(符号);
    }
    else if ((符号.标志 & 符号标志_.命名元数据_) != 0) {
        return .获取元数据声明的声明值(符号);
    }
    return 返回零值!(Value)();
}
void 检查全局引用标识符(··IR节点_.IR标识符_ n, 类型_ Ty) {
    if ((n.分类 & 标识符分类_.全局标识符_) != 0) {
        if (Ty.种类 != TypeID_.PointerTyID) {
            .错误(n, 诊断集_.global_variable_reference_must_have_pointer_type);
        }
    }
    else {
        assert((n.分类 & 标识符分类_.局部标识符_) != 0, "不是局部标识符"c);
    }
    .检查引用标识符(n);
    Value V = .有解析值!(Value)(n);
    if (V is ··null!(Value)) {
        .错误(n, 诊断集_.global_variable_reference_must_have_pointer_type);
        return;
    }
    if (V.类型 != Ty) {
        .错误(n, 诊断集_.值类型与约束类型不同);
    }
}
bool isFloatingPointTy(类型_ Ty) {
    return Ty.种类 == TypeID_.HalfTyID || Ty.种类 == TypeID_.BFloatTyID || Ty.种类 == TypeID_.FloatTyID || Ty.种类 == TypeID_.DoubleTyID || Ty.种类 == TypeID_.X86_FP80TyID || Ty.种类 == TypeID_.FP128TyID || Ty.种类 == TypeID_.PPC_FP128TyID;
}
bool isValueValidForType(类型_ Ty, APFloat_ Val) {
    // convert modifies in place, so make a copy.
    APFloat_ Val2 = new APFloat_(Val.U);
    bool losesInfo = false;
    switch (Ty.种类) {
        // FIXME rounding mode needs to be more flexible
        case TypeID_.HalfTyID: {
            if (Val2.getSemantics() == IEEEhalf()) {
                return true;
            }
            Val2.convert(IEEEhalf(), rmNearestTiesToEven, losesInfo);
            return !losesInfo;
        }
        case TypeID_.BFloatTyID: {
            if (Val2.getSemantics() == BFloat()) {
                return true;
            }
            Val2.convert(BFloat(), rmNearestTiesToEven, losesInfo);
            return !losesInfo;
        }
        case TypeID_.FloatTyID: {
            if (Val2.getSemantics() == IEEEsingle()) {
                return true;
            }
            Val2.convert(IEEEsingle(), rmNearestTiesToEven, losesInfo);
            return !losesInfo;
        }
        case TypeID_.DoubleTyID: {
            if (Val2.getSemantics() == IEEEhalf() || Val2.getSemantics() == BFloat() || Val2.getSemantics() == IEEEsingle() || Val2.getSemantics() == IEEEdouble()) {
                return true;
            }
            Val2.convert(IEEEdouble(), rmNearestTiesToEven, losesInfo);
            return !losesInfo;
        }
        case TypeID_.X86_FP80TyID: {
            return Val2.getSemantics() == IEEEhalf() || Val2.getSemantics() == BFloat() || Val2.getSemantics() == IEEEsingle() || Val2.getSemantics() == IEEEdouble() || Val2.getSemantics() == x87DoubleExtended();
        }
        case TypeID_.FP128TyID: {
            return Val2.getSemantics() == IEEEhalf() || Val2.getSemantics() == BFloat() || Val2.getSemantics() == IEEEsingle() || Val2.getSemantics() == IEEEdouble() || Val2.getSemantics() == IEEEquad();
        }
        case TypeID_.PPC_FP128TyID: {
            return Val2.getSemantics() == IEEEhalf() || Val2.getSemantics() == BFloat() || Val2.getSemantics() == IEEEsingle() || Val2.getSemantics() == IEEEdouble() || Val2.getSemantics() == PPCDoubleDouble();
        }
        default: {
            return // These can't be represented as floating point!
             false;
        } // These can't be represented as floating point!
    }
}
void 检查全局数字常量(IR数字字面量_ n, 类型_ Ty) {
    if ((n.标志 & (节点标志_.IEEEdouble | 节点标志_.x87DoubleExtended | 节点标志_.IEEEquad | 节点标志_.PPCDoubleDouble | 节点标志_.IEEEhalf | 节点标志_.BFloat)) != 0) {
        if (!.isFloatingPointTy(Ty)) {
            .错误(n, 诊断集_.floating_point_constant_invalid_for_type);
        }
        .检查数字常量(n);
        ConstantFP V = .有解析值!(ConstantFP)(n);
        if (V is ··null!(ConstantFP)) {
            .错误(n, 诊断集_.未定义的全局值);
            return;
        }
        if (!.isValueValidForType(Ty, V.Val)) {
            .错误(n, 诊断集_.floating_point_constant_invalid_for_type);
        }
        if (V.Val.getSemantics() == IEEEdouble()) {
            bool IsSNAN = V.Val.isSignaling();
            bool Ignored = false;
            if (Ty.种类 == TypeID_.HalfTyID) {
                V.Val.convert(IEEEhalf(), rmNearestTiesToEven, Ignored);
            }
            else if (Ty.种类 == TypeID_.BFloatTyID) {
                V.Val.convert(BFloat(), rmNearestTiesToEven, Ignored);
            }
            else if (Ty.种类 == TypeID_.FloatTyID) {
                V.Val.convert(IEEEsingle(), rmNearestTiesToEven, Ignored);
            }
            if (IsSNAN) {
                APInt_ Payload = V.Val.bitcastToAPInt();
                V.Val = APFloat_getSNaN(V.Val.getSemantics(), V.Val.isNegative(), Payload);
            }
        }
        V.类型 = Ty;
    }
    else {
        if (Ty.种类 != TypeID_.IntegerTyID) {
            .错误(n, 诊断集_.integer_constant_must_have_integer_type);
        }
        .检查数字常量(n);
        ConstantInt V = .有解析值!(ConstantInt)(n);
        if (V is ··null!(ConstantInt)) {
            .错误(n, 诊断集_.未定义的全局值);
            return;
        }
        APSInt_ SV = (cast(APSInt_)(V.Val));
        if (SV !is ··null!(APSInt_)) {
            V.Val = SV.extOrTrunc(Ty.位数);
        }
        V.类型 = Ty;
    }
}
void 检查常量True(节点_ n, 类型_ Ty) {
    .检查True(n);
    ConstantInt V = .有解析值!(ConstantInt)(n);
    if (V is ··null!(ConstantInt)) {
        .错误(n, 诊断集_.未定义的全局值);
        return;
    }
    if (V.类型 != Ty) {
        .错误(n, 诊断集_.值类型与约束类型不同);
    }
}
void 检查常量False(节点_ n, 类型_ Ty) {
    .检查False(n);
    ConstantInt V = .有解析值!(ConstantInt)(n);
    if (V is ··null!(ConstantInt)) {
        .错误(n, 诊断集_.未定义的全局值);
        return;
    }
    if (V.类型 != Ty) {
        .错误(n, 诊断集_.值类型与约束类型不同);
    }
}
void 检查常量Null(节点_ n, 类型_ Ty) {
    if (Ty.种类 != TypeID_.PointerTyID) {
        .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "null"d, "只能是'指针'"d);
    }
    ConstantPointerNull cn = CGet_.s·PointerNull_get((cast(指针类型_)(Ty)));
    .设置解析值(n, cn);
}
void 检查常量Undef(节点_ n, 类型_ Ty) {
    if (!.isFirstClassType(Ty) || Ty.种类 == TypeID_.LabelTyID) {
        .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "undef"d, "只能是'第一类'"d);
    }
    UndefValue cn = CGet_.s·UndefValue_get(Ty);
    .设置解析值(n, cn);
}
void 检查常量Poison(节点_ n, 类型_ Ty) {
    if (!.isFirstClassType(Ty) || Ty.种类 == TypeID_.LabelTyID) {
        .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "Poison"d, "只能是'第一类'"d);
    }
    PoisonValue cn = CGet_.s·PoisonValue_get(Ty);
    .设置解析值(n, cn);
}
void 检查常量None(节点_ n, 类型_ Ty) {
    if (Ty.种类 != TypeID_.TokenTyID) {
        .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "None"d, "只能是'token'"d);
    }
    ConstantPointerNull cn = CGet_.s·PointerNull_get((cast(指针类型_)(Ty)));
    .设置解析值(n, cn);
}
void 检查常量Zero(节点_ n, 类型_ Ty) {
    if (!.isFirstClassType(Ty) || Ty.种类 == TypeID_.LabelTyID) {
        .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "Poison"d, "只能是'第一类'"d);
    }
    Constant V = CGet_.s·getNullValue(Ty);
    .设置解析值(n, V);
}
void 检查C常量文本(c文本常量_ n, 类型_ Ty) {
    .检查C文本(n);
    Constant V = .有解析值!(Constant)(n);
    if (V is ··null!(Constant)) {
        .错误(n, 诊断集_.未定义的全局值);
        return;
    }
    if (V.类型 != Ty) {
        .错误(n, 诊断集_.值类型与约束类型不同);
    }
}
void 检查引用标识符(··IR节点_.IR标识符_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    符号_ 符号 = .解析值引用符号(n, n.内容);
    if (符号 !is ··null!(符号_)) {
        Value V = .获取符号声明值(符号);
        .设置解析值(n, V, true);
        V.解析符号 = 符号;
    }
}
void 检查数字常量(IR数字字面量_ n) {
    if ((n.标志 & (节点标志_.IEEEdouble | 节点标志_.x87DoubleExtended | 节点标志_.IEEEquad | 节点标志_.PPCDoubleDouble | 节点标志_.IEEEhalf | 节点标志_.BFloat)) != 0) {
        dstring str = n.内容;
        APFloat_ APFloatVal;
        if ((n.标志 & 节点标志_.IEEEdouble) != 0) {
            APFloatVal = new APFloat_(IEEEdouble(), str);
        }
        else if ((n.标志 & 节点标志_.x87DoubleExtended) != 0) {
            APFloatVal = new APFloat_(x87DoubleExtended(), str);
        }
        else if ((n.标志 & 节点标志_.IEEEquad) != 0) {
            APFloatVal = new APFloat_(IEEEquad(), str);
        }
        else if ((n.标志 & 节点标志_.PPCDoubleDouble) != 0) {
            APFloatVal = new APFloat_(PPCDoubleDouble(), str);
        }
        else if ((n.标志 & 节点标志_.IEEEhalf) != 0) {
            APFloatVal = new APFloat_(IEEEhalf(), str);
        }
        else // (n.标志 & 节点标志_.BFloat) != 0
         { // (n.标志 & 节点标志_.BFloat) != 0
            APFloatVal = new APFloat_(BFloat(), str);
        }
        ConstantFP V = CGet_.s·CFP_get(APFloatVal);
        .设置解析值(n, V);
    }
    else {
        APSInt_ APSIntVal;
        if ((n.标志 & 节点标志_.US十六进制_) != 0) {
            bool 是有符号的 = (n.标志 & 节点标志_.是有符号的_) != 0;
            dstring HexStr = n.内容;
            uint bits = (cast(uint)(HexStr.length * 4));
            APInt_ Tmp = new APInt_(bits, HexStr, 16);
            uint activeBits = Tmp.getActiveBits();
            if (activeBits > 0 && activeBits < bits) {
                Tmp = Tmp.trunc(activeBits);
            }
            APSIntVal = new APSInt_(Tmp, 是有符号的);
        }
        else {
            dstring Str = n.内容;
            APSIntVal = new APSInt_(Str);
        }
        ConstantInt V = CGet_.s·CInt_get((cast(APInt_)(APSIntVal)));
        .设置解析值(n, V);
    }
}
void 检查True(节点_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .设置解析值(n, .TheTrueVal);
}
void 检查False(节点_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .设置解析值(n, .TheFalseVal);
}
void 检查C文本(c文本常量_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    string 内容 = n.内容.内容;
    Constant V = CGet_.s·DataSequential_getImpl(.Int8Ty, (cast(char[])(内容)));
    .设置解析值(n, V);
}
void 检查结构字面量(结构常量表达式_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    基础节点.节点数组_!(节点_) 元素组 = n.元素组;
    if ((元素组 is null) || (元素组.原型 is ··null!(节点_[])) || 元素组.length == 0) {
        常量元素组_ es = new 常量元素组_();
        .设置解析值(n, es);
    }
    else {
        Constant[] Elts = 创建数组!(Constant)();
        foreach (节点_ e; 元素组) {
            全局表达式_ en = (cast(全局表达式_)(e));
            .检查全局表达式(en);
            Constant V = .有解析值!(Constant)(en);
            .追加!(Constant)(cast(Constant[])(Elts), V);
        }
        常量元素组_ es = new 常量元素组_(Elts);
        .设置解析值(n, es);
    }
}
void 检查全局结构字面量(结构常量表达式_ n, 类型_ Ty) {
    if (Ty.种类 == TypeID_.StructTyID) {
        .检查结构字面量(n);
        常量元素组_ V = .有解析值!(常量元素组_)(n);
        if (V is ··null!(常量元素组_)) {
            Value Val = .有解析值!(Value)(n);
            if (Val !is ··null!(Value)) {
                if (Val.类型 != Ty) {
                    .错误(n, 诊断集_.全局值与约束类型不匹配_0, "'表达式类型'与'类型'必须有相同"d);
                }
                return;
            }
            assert(false, "不可及"c);
            return;
        }
        结构类型_ ST = (cast(结构类型_)(Ty));
        if (ST.ContainedTys.length != V.Elts.length) {
            .错误(n, 诊断集_.全局值与约束类型不匹配_0, "'表达式'与'类型'必须有相同的元素数量"d);
        }
        if (ST.是压缩的 != n.是压缩的) {
            .错误(n, 诊断集_.全局值与约束类型不匹配_0, "'表达式'与'类型'的压缩属性必须相同"d);
        }
        {
            for (int i = 0; i != V.Elts.length; ++i) {
                if (V.Elts[i].类型 != ST.ContainedTys[i]) {
                    .错误(n.元素组[i], 诊断集_.值类型与约束类型不同);
                }
            }
        }
        Constant NV = CGet_.s·Struct_get((cast(结构类型_)(Ty)), V.Elts);
        .设置解析值(n, NV, true);
    }
    else {
        .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "类型"d, "必须是'结构'"d);
    }
}
void 检查向量常量字面量(向量常量表达式_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    基础节点.节点数组_!(节点_) 元素组 = n.元素组;
    if ((元素组 is null) || (元素组.原型 is ··null!(节点_[])) || 元素组.length == 0) {
        常量元素组_ es = new 常量元素组_();
        .设置解析值(n, es);
    }
    else {
        Constant[] Elts = 创建数组!(Constant)();
        类型_ 上个类型;
        foreach (节点_ e; 元素组) {
            全局表达式_ en = (cast(全局表达式_)(e));
            .检查全局表达式(en);
            Constant V = .有解析值!(Constant)(en);
            if (V is ··null!(Constant)) {
                .错误(e, 诊断集_.未定义的全局值);
                continue;
            }
            if (上个类型 is ··null!(类型_)) {
                上个类型 = V.类型;
            }
            else if (V.类型.种类 != 上个类型.种类) {
                .错误(e, 诊断集_.a0_表达式元素类型必须相同, "向量"d);
            }
            .追加!(Constant)(Elts, V);
        }
        Constant e_0 = Elts[0];
        if (e_0.类型.种类 != TypeID_.IntegerTyID && !.isFloatingPointTy(e_0.类型) && e_0.类型.种类 != TypeID_.PointerTyID) {
            .错误(n, 诊断集_.元素不是_0_的有效成员, "向量"d);
        }
        常量元素组_ es = new 常量元素组_(Elts);
        .设置解析值(n, es);
    }
}
bool isElementTypeCompatible(类型_ Ty) {
    if (Ty.种类 == TypeID_.HalfTyID || Ty.种类 == TypeID_.FloatTyID || Ty.种类 == TypeID_.BFloatTyID || Ty.种类 == TypeID_.DoubleTyID) {
        return true;
    }
    if (Ty.种类 == TypeID_.IntegerTyID) {
        整数类型_ NT = (cast(整数类型_)(Ty));
        if (NT.位数 == 8 || NT.位数 == 16 || NT.位数 == 32 || NT.位数 == 64) {
            return true;
        }
    }
    return false;
}
void 检查全局向量常量字面量(向量常量表达式_ n, 类型_ Ty) {
    if (Ty.种类 == TypeID_.FixedVectorTyID || Ty.种类 == TypeID_.ScalableVectorTyID) {
        .检查向量常量字面量(n);
        常量元素组_ V = .有解析值!(常量元素组_)(n);
        if (V is ··null!(常量元素组_)) {
            Value Val = .有解析值!(Value)(n);
            if (Val !is ··null!(Value)) {
                if (Val.类型 != Ty) {
                    .错误(n, 诊断集_.全局值与约束类型不匹配_0, "'表达式类型'与'类型'必须有相同"d);
                }
                return;
            }
            assert(false, "不可及"c);
            return;
        }
        if ((V.Elts is ··null!(Constant[])) || V.Elts.length == 0) {
            .错误(n, 诊断集_.向量表达式元素不能为空);
        }
        else {
            Constant C = V.Elts[0];
            向量类型_ T = TGet_.s·VTy_get(C.类型, false, (cast(uint)(V.Elts.length)));
            Constant NV = CGet_.s·Vector_get(V.Elts);
            if (T != Ty) {
                .错误(n, 诊断集_.全局值与约束类型不匹配_0, "'表达式类型'与'类型'必须有相同"d);
            }
            else {
                .设置解析值(n, NV, true);
            }
        }
    }
    else {
        .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "类型"d, "必须是'向量'"d);
    }
}
void 检查数组常量字面量(数组常量表达式_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    基础节点.节点数组_!(节点_) 元素组 = n.元素组;
    if ((元素组 is null) || (元素组.原型 is ··null!(节点_[])) || 元素组.length == 0) {
        常量元素组_ es = new 常量元素组_();
        .设置解析值(n, es);
    }
    else {
        Constant[] Elts = 创建数组!(Constant)();
        类型_ 上个类型;
        foreach (节点_ e; 元素组) {
            全局表达式_ en = (cast(全局表达式_)(e));
            .检查全局表达式(en);
            Constant V = .有解析值!(Constant)(en);
            if (V is ··null!(Constant)) {
                .错误(e, 诊断集_.未定义的全局值);
                continue;
            }
            if (上个类型 is ··null!(类型_)) {
                上个类型 = V.类型;
            }
            else if (V.类型.种类 != 上个类型.种类) {
                .错误(e, 诊断集_.a0_表达式元素类型必须相同, "向量"d);
            }
            .追加!(Constant)(Elts, V);
        }
        Constant e_0 = Elts[0];
        if (e_0.类型.种类 != TypeID_.IntegerTyID && !.isFloatingPointTy(e_0.类型) && e_0.类型.种类 != TypeID_.PointerTyID) {
            .错误(n, 诊断集_.元素不是_0_的有效成员, "向量"d);
        }
        常量元素组_ es = new 常量元素组_(Elts);
        .设置解析值(n, es);
    }
}
void 检查全局数组常量字面量(数组常量表达式_ n, 类型_ Ty) {
    if (Ty.种类 == TypeID_.ArrayTyID) {
        .检查数组常量字面量(n);
        常量元素组_ V = .有解析值!(常量元素组_)(n);
        if (V is ··null!(常量元素组_)) {
            Value Val = .有解析值!(Value)(n);
            if (Val !is ··null!(Value)) {
                if (Val.类型 != Ty) {
                    .错误(n, 诊断集_.全局值与约束类型不匹配_0, "'表达式类型'与'类型'必须有相同"d);
                }
                return;
            }
            assert(false, "不可及"c);
            return;
        }
        if ((V.Elts is ··null!(Constant[])) || V.Elts.length == 0) {
            ConstantAggregateZero NV = CGet_.s·AggregateZero_get(Ty);
            .设置解析值(n, NV, true);
        }
        else {
            Constant C = V.Elts[0];
            数组类型_ T = TGet_.s·ArrTy_get(C.类型, (cast(uint)(V.Elts.length)));
            Constant NV = CGet_.s·Array_get(T, V.Elts);
            if (T != Ty) {
                .错误(n, 诊断集_.全局值与约束类型不匹配_0, "'表达式类型'与'类型'必须有相同"d);
            }
            else {
                .设置解析值(n, NV, true);
            }
        }
    }
    else {
        .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "类型"d, "必须是'数组'"d);
    }
}
void 检查块地址表常量表达式(块地址表常量表达式_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查ValID(n.函数_);
    Value F = .有解析值!(Value)(n.函数_);
    if ((F is ··null!(Value)) || F.种类 != ValueTy_.FunctionVal) {
        .错误(n.函数_, 诊断集_.未定义的全局值);
    }
    else {
        .检查ValID(n.标签);
        Value B = .有解析值!(Value)(n.函数_);
        if ((B is ··null!(Value)) || B.种类 != ValueTy_.BasicBlockVal) {
            .错误(n.标签, 诊断集_.未发现符号_0, "基本块"d);
        }
        else {
            Function FV = (cast(Function)(F));
            BasicBlock BB = (cast(BasicBlock)(B));
            if (BB.符号.父符号 != FV.符号) {
                .错误(n.标签, 诊断集_.未发现符号_0, "基本块"d);
            }
            BlockAddress V = CGet_.s·BlockAddress_get(FV, BB);
            .设置解析值(n, V);
        }
    }
}
void 检查全局块地址表常量表达式(块地址表常量表达式_ n, 类型_ Ty) {
    .检查ValID(n);
    BlockAddress V = .有解析值!(BlockAddress)(n);
    if (V is ··null!(BlockAddress)) {
        .错误(n, 诊断集_.未定义的全局值);
    }
    else {
        if (V.类型 != Ty) {
            .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "类型"d, "必须是'i8*'"d);
        }
    }
}
void 检查DSO局部等效常量表达式(DSO局部等效常量表达式_ n) {
    .检查ValID(n.函数_);
    GlobalValue GV = .有解析值!(GlobalValue)(n.函数_);
    if (GV is ··null!(GlobalValue)) {
        .错误(n.函数_, 诊断集_.未定义的全局值);
    }
    else {
        DSOLocalEquivalent V = CGet_.s·DSOLocalEquivalent_get(GV);
        .设置解析值(n, V);
    }
}
void 检查全局DSO局部等效常量表达式(DSO局部等效常量表达式_ n, 类型_ Ty) {
    .检查ValID(n);
    DSOLocalEquivalent V = .有解析值!(DSOLocalEquivalent)(n);
    if (V is ··null!(DSOLocalEquivalent)) {
        .错误(n, 诊断集_.未定义的全局值);
    }
    else {
        if (V.类型 != Ty) {
            .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "类型"d, "必须是'全局值'"d);
        }
    }
}
void 检查内联汇编常量表达式(内联汇编常量表达式_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    dstring StrVal = n.StrVal.内容;
    dstring StrVal2 = n.StrVal2.内容;
    bool hasSideEffect = n.HasSideEffect ? true : false;
    bool alignStack = n.AlignStack ? true : false;
    AsmDialect asmDialect = n.AsmDialect ? AsmDialect.AD_Intel : AsmDialect.AD_ATT;
    bool canThrow = n.CanThrow ? true : false;
    InlineAsm V = new InlineAsm(StrVal, StrVal2, hasSideEffect, alignStack, asmDialect, canThrow);
    .设置解析值(n, V);
}
void 检查全局内联汇编常量表达式(内联汇编常量表达式_ n, 类型_ _) {
    .检查ValID(n);
    Value asmV = .有解析值!(Value)(n);
    if (asmV is ··null!(Value)) {
        .错误(n, 诊断集_.未定义的全局值);
    }
    else {
        if (asmV.种类 == ValueTy_.InlineAsmVal) {
            InlineAsm V = (cast(InlineAsm)(asmV));
            if ((V.FTy is ··null!(函数类型_)) || V.FTy.种类 != TypeID_.FunctionTyID || InlineAsm_Verify((cast(函数类型_)(V.FTy)), V.Constraints)) {
                .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "内联汇编"d, "验证失败"d);
            }
            else {
                InlineAsm aV = CGet_.s·InlineAsm_get(V);
                .设置解析值(n, aV, true);
            }
        }
    }
}
void 检查常量转换类节点(常量转换类节点_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    节点_ op = n.op;
    switch (op.目标种类) {
        case ISK.trunc:
        case ISK.zext:
        case ISK.sext:
        case ISK.fptrunc:
        case ISK.fpext:
        case ISK.bitcast:
        case ISK.addrspacecast:
        case ISK.uitofp:
        case ISK.sitofp:
        case ISK.fptoui:
        case ISK.fptosi:
        case ISK.inttoptr:
        case ISK.ptrtoint: {
            节点_ srcVal = n.srcVal;
            节点_ DestTy = n.DestTy;
            .检查全局表达式((cast(全局表达式_)(srcVal)));
            Constant C = .有解析值!(Constant)(srcVal);
            类型_ Ty = .获取类型节点的类型(DestTy);
            InstructionKind_ Opc = ISK转为CastOpc(op.目标种类);
            Constant 值 = CEGet_.s·getCast(Opc, C, Ty, false);
            .设置解析值(n, 值);
        }
        default: break;
    }
}
void 检查全局常量转换类节点(常量转换类节点_ n, 类型_ Ty) {
    .检查ValID(n);
    Constant V = .有解析值!(Constant)(n);
    if (V is ··null!(Constant)) {
        .错误(n, 诊断集_.未定义的全局值);
    }
    else {
        if (V.类型 != Ty) {
            .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "类型"d, "必须是'全局值'"d);
        }
    }
}
void 检查提取值常量表达式(提取值常量表达式_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查全局表达式((cast(全局表达式_)(n.Val)));
    Constant C = .有解析值!(Constant)(n.Val);
    if (C is ··null!(Constant)) {
        .错误(n.Val, 诊断集_.未定义的全局值);
    }
    else {
        uint[] idx = 创建数组!(uint)();
        foreach (节点_ i; n.Indices) {
            ulong iv = (cast(IR数字字面量_)(i)).整数值;
            uint i32_ = (cast(uint)(iv));
            if (i32_ != iv) {
                .错误(i, 诊断集_.整数溢出);
            }
            .追加!(uint)(idx, i32_);
        }
        if (!.isAggregateType(C.类型)) {
            节点_ err = (cast(全局表达式_)(n.Val)).类型;
            .错误(err, 诊断集_.extractvalue_operand_must_be_aggregate_type);
        }
        if (GEV_.s·getIndexedType(C.类型, idx) is ··null!(类型_)) {
            .错误(n, 诊断集_.invalid_indices_for_extractvalue);
        }
        Constant 值 = CEGet_.s·getExtractValue(C, idx);
        if (值 !is ··null!(Constant)) {
            .设置解析值(n, 值);
        }
    }
}
void 检查全局提取值常量表达式(提取值常量表达式_ n, 类型_ Ty) {
    .检查ValID(n);
    Constant V = .有解析值!(Constant)(n);
    if (V is ··null!(Constant)) {
        .错误(n, 诊断集_.未定义的全局值);
    }
    else {
        if (V.类型 != Ty) {
            .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "类型"d, "必须是'全局值'"d);
        }
    }
}
void 检查插入值常量表达式(插入值常量表达式_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查全局表达式((cast(全局表达式_)(n.Val0)));
    Constant C1 = .有解析值!(Constant)(n.Val0);
    if (C1 is ··null!(Constant)) {
        .错误(n.Val0, 诊断集_.未定义的全局值);
    }
    else {
        .检查全局表达式((cast(全局表达式_)(n.Val1)));
        Constant C2 = .有解析值!(Constant)(n.Val1);
        if (C2 is ··null!(Constant)) {
            .错误(n.Val1, 诊断集_.未定义的全局值);
        }
        else {
            uint[] idx = 创建数组!(uint)();
            foreach (节点_ i; n.Indices) {
                ulong iv = (cast(IR数字字面量_)(i)).整数值;
                uint i32_ = (cast(uint)(iv));
                if (i32_ != iv) {
                    .错误(i, 诊断集_.整数溢出);
                }
                .追加!(uint)(idx, i32_);
            }
            if (!.isAggregateType(C1.类型)) {
                节点_ err = (cast(全局表达式_)(n.Val0)).类型;
                .错误(err, 诊断集_.extractvalue_operand_must_be_aggregate_type);
            }
            类型_ IndexedType = GEV_.s·getIndexedType(C1.类型, idx);
            if (IndexedType is ··null!(类型_)) {
                .错误(n, 诊断集_.invalid_indices_for_insertvalue);
            }
            if (C2.类型 != IndexedType) {
                .错误(n.Val1, 诊断集_.invalid_indices_for_insertvalue);
            }
            Constant 值 = CEGet_.s·getInsertValue(C1, C2, idx);
            if (值 !is ··null!(Constant)) {
                .设置解析值(n, 值);
            }
        }
    }
}
void 检查全局插入值常量表达式(插入值常量表达式_ n, 类型_ Ty) {
    .检查ValID(n);
    Constant V = .有解析值!(Constant)(n);
    if (V is ··null!(Constant)) {
        .错误(n, 诊断集_.未定义的全局值);
    }
    else {
        if (V.类型 != Ty) {
            .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "类型"d, "必须是'全局值'"d);
        }
    }
}
void 检查比较类常量表达式(比较类常量表达式_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    节点_ kind = n.kind;
    节点_ PredVal = n.PredVal;
    CmpInst_Predicate_ Pred = ISK转为CmpInst_Predicate(PredVal.目标种类);
    .检查全局表达式((cast(全局表达式_)(n.Val0)));
    Constant Val0 = .有解析值!(Constant)(n.Val0);
    .检查全局表达式((cast(全局表达式_)(n.Val1)));
    Constant Val1 = .有解析值!(Constant)(n.Val1);
    if ((Val0 is ··null!(Constant)) || (Val1 is ··null!(Constant)) || Pred == CmpInst_Predicate_.无效值_) {
        节点_ err = (Val0 is ··null!(Constant)) ? n.Val0 : (Val1 is ··null!(Constant)) ? n.Val1 : n;
        .错误(err, 诊断集_.未定义的全局值);
    }
    else {
        if (Val0.类型 != Val1.类型) {
            .错误(n.Val1, 诊断集_.compare_operands_must_have_the_same_type);
        }
        if (kind.目标种类 == ISK.fcmp) {
            if (!.isFPOrFPVectorTy(Val0.类型)) {
                .错误(n.Val0, 诊断集_.fcmp_requires_floating_point_operands);
            }
            Constant 值 = CEGet_.s·getFCmp(Pred, Val0, Val1);
            if (值 !is ··null!(Constant)) {
                .设置解析值(n, 值);
            }
        }
        else {
            assert(kind.目标种类 == ISK.icmp, "错误的 比较指令"c);
            if (!.isIntOrIntVectorTy(Val0.类型) || !.isPtrOrPtrVectorTy(Val0.类型)) {
                .错误(n.Val0, 诊断集_.icmp_requires_pointer_or_integer_operands);
            }
            Constant 值 = CEGet_.s·getICmp(Pred, Val0, Val1);
            if (值 !is ··null!(Constant)) {
                .设置解析值(n, 值);
            }
        }
    }
}
void 检查全局比较类常量表达式(比较类常量表达式_ n, 类型_ Ty) {
    .检查ValID(n);
    Constant V = .有解析值!(Constant)(n);
    if (V is ··null!(Constant)) {
        .错误(n, 诊断集_.未定义的全局值);
    }
    else {
        if (V.类型 != Ty) {
            .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "类型"d, "必须是'全局值'"d);
        }
    }
}
void 检查取反常量表达式(取反常量表达式_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查全局表达式((cast(全局表达式_)(n.Val)));
    Constant Val = .有解析值!(Constant)(n.Val);
    if (Val is ··null!(Constant)) {
        .错误(n, 诊断集_.未定义的全局值);
    }
    else {
        if (!.isFPOrFPVectorTy(Val.类型)) {
            .错误(n.Val, 诊断集_.constexpr_requires_fp_operands);
        }
        uint Flags = 0;
        Constant 值 = CEGet_.s·get(InstructionKind_.FNeg, Val, Flags);
        if (值 !is ··null!(Constant)) {
            .设置解析值(n, 值);
        }
    }
}
void 检查全局取反常量表达式(取反常量表达式_ n, 类型_ Ty) {
    .检查ValID(n);
    Constant V = .有解析值!(Constant)(n);
    if (V is ··null!(Constant)) {
        .错误(n, 诊断集_.未定义的全局值);
    }
    else {
        if (V.类型 != Ty) {
            .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "类型"d, "必须是'全局值'"d);
        }
    }
}
void 检查全局二元常量表达式(二元常量表达式_ n, 类型_ Ty) {
    .检查ValID(n);
    Constant V = .有解析值!(Constant)(n);
    if (V is ··null!(Constant)) {
        .错误(n, 诊断集_.未定义的全局值);
    }
    else {
        if (V.类型 != Ty) {
            .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "类型"d, "必须是'全局值'"d);
        }
    }
}
void 检查二元常量表达式(二元常量表达式_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    InstructionKind_ Opc = ISK转为二元运算指令(n.op.目标种类);
    .检查全局表达式((cast(全局表达式_)(n.Val0)));
    Constant Val0 = .有解析值!(Constant)(n.Val0);
    .检查全局表达式((cast(全局表达式_)(n.Val1)));
    Constant Val1 = .有解析值!(Constant)(n.Val1);
    if ((Val0 is ··null!(Constant)) || (Val1 is ··null!(Constant)) || Opc == InstructionKind_.无效值_) {
        节点_ err = (Val0 is ··null!(Constant)) ? n.Val0 : (Val1 is ··null!(Constant)) ? n.Val1 : n;
        .错误(err, 诊断集_.未定义的全局值);
    }
    else {
        switch (Opc) {
            case InstructionKind_.Add:
            case InstructionKind_.Sub:
            case InstructionKind_.Mul:
            case InstructionKind_.UDiv:
            case InstructionKind_.SDiv:
            case InstructionKind_.URem:
            case InstructionKind_.SRem:
            case InstructionKind_.Shl:
            case InstructionKind_.AShr:
            case InstructionKind_.LShr: {
                if (!.isIntOrIntVectorTy(Val0.类型)) {
                    .错误(n.Val0, 诊断集_.constexpr_requires_integer_operands);
                }
                break;
            }
            case InstructionKind_.FAdd:
            case InstructionKind_.FSub:
            case InstructionKind_.FMul:
            case InstructionKind_.FDiv:
            case InstructionKind_.FRem: {
                if (!.isFPOrFPVectorTy(Val0.类型)) {
                    .错误(n.Val0, 诊断集_.constexpr_requires_fp_operands);
                }
                break;
            }
            default: break;
        }
        uint Flags = 0;
        if (n.NUW !is ··null!(节点_)) {
            Flags |= 1;
        }
        if (n.NSW !is ··null!(节点_)) {
            Flags |= 2;
        }
        if (n.Exact !is ··null!(节点_)) {
            Flags |= 1;
        }
        Constant 值 = CEGet_.s·get(Opc, Val0, Val1, Flags);
        if (值 !is ··null!(Constant)) {
            .设置解析值(n, 值);
        }
    }
}
void 检查逻辑类常量表达式(逻辑类常量表达式_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    InstructionKind_ Opc = ISK转为逻辑运算指令(n.op.目标种类);
    .检查全局表达式((cast(全局表达式_)(n.Val0)));
    Constant Val0 = .有解析值!(Constant)(n.Val0);
    .检查全局表达式((cast(全局表达式_)(n.Val1)));
    Constant Val1 = .有解析值!(Constant)(n.Val1);
    if ((Val0 is ··null!(Constant)) || (Val1 is ··null!(Constant)) || Opc == InstructionKind_.无效值_) {
        节点_ err = (Val0 is ··null!(Constant)) ? n.Val0 : (Val1 is ··null!(Constant)) ? n.Val1 : n;
        .错误(err, 诊断集_.未定义的全局值);
    }
    else {
        if (Val0.类型 != Val1.类型) {
            .错误(n.Val1, 诊断集_.operands_of_constexpr_must_have_same_type);
        }
        if (!.isIntOrIntVectorTy(Val0.类型)) {
            .错误(n.Val1, 诊断集_.constexpr_requires_integer_or_integer_vector_operands);
        }
        Constant 值 = CEGet_.s·get(Opc, Val0, Val1);
        if (值 !is ··null!(Constant)) {
            .设置解析值(n, Val1);
        }
    }
}
void 检查全局逻辑类常量表达式(逻辑类常量表达式_ n, 类型_ Ty) {
    .检查ValID(n);
    Constant V = .有解析值!(Constant)(n);
    if (V is ··null!(Constant)) {
        .错误(n, 诊断集_.未定义的全局值);
    }
    else {
        if (V.类型 != Ty) {
            .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "类型"d, "必须是'全局值'"d);
        }
    }
}
void 检查获取元素指针常量表达式(获取元素指针常量表达式_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    类型_ Ty = .获取类型节点的类型(n.类型);
    Constant[] Elts = 创建数组!(Constant)();
    uint InRangeOp = -1;
    bool InBounds = false;
    InBounds = n.在界内 !is ··null!(节点_);
    {
        for (int i = 0; i < n.索引表.length; ++i) {
            全局表达式_ Index = (cast(全局表达式_)(n.索引表[i]));
            .检查全局表达式(Index);
            if ((Index.InRangeOp !is ··null!(节点_)) && InRangeOp == -1) {
                InRangeOp = i;
            }
            else if (Index.InRangeOp !is ··null!(节点_)) {
                .错误(Index.InRangeOp, 诊断集_.元素不是_0_的有效成员, "获取约束指针常量表达式"d);
            }
            Constant V = .有解析值!(Constant)(Index);
            .追加!(Constant)(cast(Constant[])(Elts), V);
        }
    }
    if (Elts.length == 0 || !.isPtrOrPtrVectorTy(Elts[0].类型)) {
        节点_ err = n.索引表.length > 0 ? n.索引表[0] : n;
        .错误(err, 诊断集_.base_of_getelementptr_must_be_a_pointer);
    }
    类型_ BaseType = Elts[0].类型;
    指针类型_ BasePointerType = .cast_!(指针类型_)(.getScalarType(BaseType));
    if (Ty != BasePointerType) {
        节点_ err = n.索引表.length > 0 ? n.索引表[0] : n;
        .错误(err, 诊断集_.explicit_pointee_type_doesn_t_match_operand_s_pointee_type);
    }
    uint GEPWidth = .isVectorType(BaseType) ? .cast_!(向量类型_)(BaseType).数量 : 0;
    Constant[] Indices = Elts[1 .. $];
    {
        for (int i = 0; i < Indices.length; ++i) {
            Constant Val = Indices[i];
            类型_ ValTy = Val.类型;
            if (!.isIntOrIntVectorTy(ValTy)) {
                节点_ err = n.索引表[i + 1];
                .错误(err, 诊断集_.getelementptr_index_must_be_an_integer);
            }
            向量类型_ ValVTy = .dyn_cast!(向量类型_)(ValTy);
            if (ValVTy !is ··null!(向量类型_)) {
                uint ValNumEl = ValVTy.数量;
                if (GEPWidth != 0 && GEPWidth != ValNumEl) {
                    节点_ err = n.索引表[i + 1];
                    .错误(err, 诊断集_.getelementptr_vector_index_has_a_wrong_number_of_elements);
                }
                GEPWidth = ValNumEl;
            }
        }
    }
    类型_[] Visited = 创建数组!(类型_)();
    if (Indices.length > 0 && TY_.s·isSized(Ty)) {
        .追加!(类型_)(Visited, Ty);
    }
    if (InRangeOp != -1) {
        if (InRangeOp == 0) {
            .错误(n.索引表[0], 诊断集_.inrange_keyword_may_not_appear_on_pointer_operand);
        }
        --InRangeOp;
    }
    Constant 值 = CEGet_.s·getGetElementPtr(Ty, Elts[0], cast(Value[])(Indices), InBounds, InRangeOp);
    if (值 !is ··null!(Constant)) {
        .设置解析值(n, 值);
    }
}
void 检查全局获取元素指针常量表达式(获取元素指针常量表达式_ n, 类型_ Ty) {
    .检查ValID(n);
    Constant V = .有解析值!(Constant)(n);
    if (V is ··null!(Constant)) {
        .错误(n, 诊断集_.未定义的全局值);
    }
    else {
        if (V.类型 != Ty) {
            .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "类型"d, "必须是'全局值'"d);
        }
    }
}
void 检查向量洗牌常量表达式(向量洗牌常量表达式_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查全局表达式((cast(全局表达式_)(n.Val0)));
    Constant Val0 = .有解析值!(Constant)(n.Val0);
    .检查全局表达式((cast(全局表达式_)(n.Val1)));
    Constant Val1 = .有解析值!(Constant)(n.Val1);
    .检查全局表达式((cast(全局表达式_)(n.Val2)));
    Constant Val2 = .有解析值!(Constant)(n.Val2);
    if ((Val0 is ··null!(Constant)) || (Val1 is ··null!(Constant)) || (Val2 is ··null!(Constant))) {
        节点_ err = (Val0 is ··null!(Constant)) ? n.Val0 : (Val1 is ··null!(Constant)) ? n.Val1 : (Val2 is ··null!(Constant)) ? n.Val2 : n;
        .错误(err, 诊断集_.未定义的全局值);
    }
    else {
        if (!SVI_.s·isValidOperands(Val0, Val1, Val2)) {
            .错误(n, 诊断集_.nvalid_operands_to_0, "shufflevector"d);
        }
        int[] Mask = SVI_.s·getShuffleMask(Val2);
        Constant 值 = CEGet_.s·getShuffleVector(Val0, Val1, Mask);
        if (值 !is ··null!(Constant)) {
            .设置解析值(n, 值);
        }
    }
}
void 检查全局向量洗牌常量表达式(向量洗牌常量表达式_ n, 类型_ Ty) {
    .检查ValID(n);
    Constant V = .有解析值!(Constant)(n);
    if (V is ··null!(Constant)) {
        .错误(n, 诊断集_.未定义的全局值);
    }
    else {
        if (V.类型 != Ty) {
            .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "类型"d, "必须是'全局值'"d);
        }
    }
}
void 检查插入元素常量表达式(插入元素常量表达式_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查全局表达式((cast(全局表达式_)(n.Val0)));
    Constant Val0 = .有解析值!(Constant)(n.Val0);
    .检查全局表达式((cast(全局表达式_)(n.Val1)));
    Constant Val1 = .有解析值!(Constant)(n.Val1);
    .检查全局表达式((cast(全局表达式_)(n.Val2)));
    Constant Val2 = .有解析值!(Constant)(n.Val2);
    if ((Val0 is ··null!(Constant)) || (Val1 is ··null!(Constant)) || (Val2 is ··null!(Constant))) {
        节点_ err = (Val0 is ··null!(Constant)) ? n.Val0 : (Val1 is ··null!(Constant)) ? n.Val1 : (Val2 is ··null!(Constant)) ? n.Val2 : n;
        .错误(err, 诊断集_.未定义的全局值);
    }
    else {
        if (!IEI_.s·isValidOperands(Val0, Val1, Val2)) {
            .错误(n, 诊断集_.nvalid_operands_to_0, "insertelement"d);
        }
        Constant 值 = CEGet_.s·getInsertElement(Val0, Val1, Val2);
        if (值 !is ··null!(Constant)) {
            .设置解析值(n, 值);
        }
    }
}
void 检查全局插入元素常量表达式(插入元素常量表达式_ n, 类型_ Ty) {
    .检查ValID(n);
    Constant V = .有解析值!(Constant)(n);
    if (V is ··null!(Constant)) {
        .错误(n, 诊断集_.未定义的全局值);
    }
    else {
        if (V.类型 != Ty) {
            .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "类型"d, "必须是'全局值'"d);
        }
    }
}
void 检查提取元素常量表达式(提取元素常量表达式_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查全局表达式((cast(全局表达式_)(n.Val0)));
    Constant Val0 = .有解析值!(Constant)(n.Val0);
    .检查全局表达式((cast(全局表达式_)(n.Val1)));
    Constant Val1 = .有解析值!(Constant)(n.Val1);
    if ((Val0 is ··null!(Constant)) || (Val1 is ··null!(Constant))) {
        节点_ err = (Val0 is ··null!(Constant)) ? n.Val0 : (Val1 is ··null!(Constant)) ? n.Val1 : n;
        .错误(err, 诊断集_.未定义的全局值);
    }
    else {
        if (!EEI_.s·isValidOperands(Val0, Val1)) {
            .错误(n, 诊断集_.nvalid_operands_to_0, "extractelement"d);
        }
        Constant 值 = CEGet_.s·getExtractElement(Val0, Val1);
        if (值 !is ··null!(Constant)) {
            .设置解析值(n, 值);
        }
    }
}
void 检查全局提取元素常量表达式(提取元素常量表达式_ n, 类型_ Ty) {
    .检查ValID(n);
    Constant V = .有解析值!(Constant)(n);
    if (V is ··null!(Constant)) {
        .错误(n, 诊断集_.未定义的全局值);
    }
    else {
        if (V.类型 != Ty) {
            .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "类型"d, "必须是'全局值'"d);
        }
    }
}
void 检查选择常量表达式(选择常量表达式_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查全局表达式((cast(全局表达式_)(n.Val0)));
    Constant Val0 = .有解析值!(Constant)(n.Val0);
    .检查全局表达式((cast(全局表达式_)(n.Val1)));
    Constant Val1 = .有解析值!(Constant)(n.Val1);
    .检查全局表达式((cast(全局表达式_)(n.Val2)));
    Constant Val2 = .有解析值!(Constant)(n.Val2);
    if ((Val0 is ··null!(Constant)) || (Val1 is ··null!(Constant)) || (Val2 is ··null!(Constant))) {
        节点_ err = (Val0 is ··null!(Constant)) ? n.Val0 : (Val1 is ··null!(Constant)) ? n.Val1 : (Val2 is ··null!(Constant)) ? n.Val2 : n;
        .错误(err, 诊断集_.未定义的全局值);
    }
    else {
        if (.SelectInst_areInvalidOperands(Val0, Val1, Val2) !is ··null!(dstring)) {
            .错误(n, 诊断集_.nvalid_operands_to_0, "select"d);
        }
        Constant 值 = CEGet_.s·getSelect(Val0, Val1, Val2);
        if (值 !is ··null!(Constant)) {
            .设置解析值(n, 值);
        }
    }
}
void 检查全局选择常量表达式(选择常量表达式_ n, 类型_ Ty) {
    .检查ValID(n);
    Constant V = .有解析值!(Constant)(n);
    if (V is ··null!(Constant)) {
        .错误(n, 诊断集_.未定义的全局值);
    }
    else {
        if (V.类型 != Ty) {
            .错误(n, 诊断集_.值类型与约束类型不匹配_0_1_类型, "类型"d, "必须是'全局值'"d);
        }
    }
}
void 检查ValID(节点_ nn) {
    switch (nn.目标种类) {
        case ISK.标识符: {
            return .检查引用标识符((cast(标识符_)(nn)));
        }
        case ISK.数字字面量: {
            return .检查数字常量((cast(IR数字字面量_)(nn)));
        }
        case ISK.true_: {
            return .检查True(nn);
        }
        case ISK.false_: {
            return .检查False(nn);
        }
        case ISK.c文本常量: {
            return .检查C文本((cast(c文本常量_)(nn)));
        }
        case ISK.结构常量表达式: {
            return .检查结构字面量((cast(结构常量表达式_)(nn)));
        }
        case ISK.向量常量表达式: {
            return .检查向量常量字面量((cast(向量常量表达式_)(nn)));
        }
        case ISK.数组常量表达式: {
            return .检查数组常量字面量((cast(数组常量表达式_)(nn)));
        }
        case ISK.块地址表常量表达式: {
            return .检查块地址表常量表达式((cast(块地址表常量表达式_)(nn)));
        }
        case ISK.DSO局部等效常量表达式: {
            return .检查DSO局部等效常量表达式((cast(DSO局部等效常量表达式_)(nn)));
        }
        case ISK.内联汇编常量表达式: {
            return .检查内联汇编常量表达式((cast(内联汇编常量表达式_)(nn)));
        }
        case ISK.常量转换类节点: {
            return .检查常量转换类节点((cast(常量转换类节点_)(nn)));
        }
        case ISK.提取值常量表达式: {
            return .检查提取值常量表达式((cast(提取值常量表达式_)(nn)));
        }
        case ISK.插入值常量表达式: {
            return .检查插入值常量表达式((cast(插入值常量表达式_)(nn)));
        }
        case ISK.比较类常量表达式: {
            return .检查比较类常量表达式((cast(比较类常量表达式_)(nn)));
        }
        case ISK.取反常量表达式: {
            return .检查取反常量表达式((cast(取反常量表达式_)(nn)));
        }
        case ISK.二元常量表达式: {
            return .检查二元常量表达式((cast(二元常量表达式_)(nn)));
        }
        case ISK.逻辑类常量表达式: {
            return .检查逻辑类常量表达式((cast(逻辑类常量表达式_)(nn)));
        }
        case ISK.获取元素指针常量表达式: {
            return .检查获取元素指针常量表达式((cast(获取元素指针常量表达式_)(nn)));
        }
        case ISK.向量洗牌常量表达式: {
            return .检查向量洗牌常量表达式((cast(向量洗牌常量表达式_)(nn)));
        }
        case ISK.插入元素常量表达式: {
            return .检查插入元素常量表达式((cast(插入元素常量表达式_)(nn)));
        }
        case ISK.提取元素常量表达式: {
            return .检查提取元素常量表达式((cast(提取元素常量表达式_)(nn)));
        }
        case ISK.选择常量表达式: {
            return .检查选择常量表达式((cast(选择常量表达式_)(nn)));
        }
        default: {
            assert(false, "不可及"c);
            return;
        }
    }
}
void 检查全局表达式(全局表达式_ 表达式) {
    if (.有解析值!(Value)(表达式) !is ··null!(Value)) {
        return;
    }
    .检查表达式(表达式.表达式, 表达式.类型);
    Constant V = .有解析值!(Constant)(表达式.表达式);
    if (V is ··null!(Constant)) {
        .错误(表达式.表达式, 诊断集_.全局表达式必须是常量值);
    }
    else {
        .设置解析值(表达式, V);
    }
}
void 检查表达式2(节点_ 表达式, 类型_ Ty) {
    if (Ty.种类 == TypeID_.FunctionTyID) {
        .错误(表达式, 诊断集_.functions_are_not_values_refer_to_them_as_pointers);
    }
    switch (表达式.目标种类) {
        case ISK.标识符: {
            return .检查全局引用标识符((cast(标识符_)(表达式)), Ty);
        }
        case ISK.数字字面量: {
            return .检查全局数字常量((cast(IR数字字面量_)(表达式)), Ty);
        }
        case ISK.true_: {
            return .检查常量True(表达式, Ty);
        }
        case ISK.false_: {
            return .检查常量False(表达式, Ty);
        }
        case ISK.null_: {
            return .检查常量Null(表达式, Ty);
        }
        case ISK.undef: {
            return .检查常量Undef(表达式, Ty);
        }
        case ISK.none: {
            return .检查常量None(表达式, Ty);
        }
        case ISK.poison: {
            return .检查常量Poison(表达式, Ty);
        }
        case ISK.zeroinitializer: {
            return .检查常量Zero(表达式, Ty);
        }
        case ISK.c文本常量: {
            return .检查C常量文本((cast(c文本常量_)(表达式)), Ty);
        }
        case ISK.结构常量表达式: {
            return .检查全局结构字面量((cast(结构常量表达式_)(表达式)), Ty);
        }
        case ISK.向量常量表达式: {
            return .检查全局向量常量字面量((cast(向量常量表达式_)(表达式)), Ty);
        }
        case ISK.数组常量表达式: {
            return .检查全局数组常量字面量((cast(数组常量表达式_)(表达式)), Ty);
        }
        case ISK.块地址表常量表达式: {
            return .检查全局块地址表常量表达式((cast(块地址表常量表达式_)(表达式)), Ty);
        }
        case ISK.DSO局部等效常量表达式: {
            return .检查全局DSO局部等效常量表达式((cast(DSO局部等效常量表达式_)(表达式)), Ty);
        }
        case ISK.内联汇编常量表达式: {
            return .检查全局内联汇编常量表达式((cast(内联汇编常量表达式_)(表达式)), Ty);
        }
        case ISK.常量转换类节点: {
            return .检查全局常量转换类节点((cast(常量转换类节点_)(表达式)), Ty);
        }
        case ISK.提取值常量表达式: {
            return .检查全局提取值常量表达式((cast(提取值常量表达式_)(表达式)), Ty);
        }
        case ISK.插入值常量表达式: {
            return .检查全局插入值常量表达式((cast(插入值常量表达式_)(表达式)), Ty);
        }
        case ISK.比较类常量表达式: {
            return .检查全局比较类常量表达式((cast(比较类常量表达式_)(表达式)), Ty);
        }
        case ISK.取反常量表达式: {
            return .检查全局取反常量表达式((cast(取反常量表达式_)(表达式)), Ty);
        }
        case ISK.二元常量表达式: {
            return .检查全局二元常量表达式((cast(二元常量表达式_)(表达式)), Ty);
        }
        case ISK.逻辑类常量表达式: {
            return .检查全局逻辑类常量表达式((cast(逻辑类常量表达式_)(表达式)), Ty);
        }
        case ISK.获取元素指针常量表达式: {
            return .检查全局获取元素指针常量表达式((cast(获取元素指针常量表达式_)(表达式)), Ty);
        }
        case ISK.向量洗牌常量表达式: {
            return .检查全局向量洗牌常量表达式((cast(向量洗牌常量表达式_)(表达式)), Ty);
        }
        case ISK.插入元素常量表达式: {
            return .检查全局插入元素常量表达式((cast(插入元素常量表达式_)(表达式)), Ty);
        }
        case ISK.提取元素常量表达式: {
            return .检查全局提取元素常量表达式((cast(提取元素常量表达式_)(表达式)), Ty);
        }
        case ISK.选择常量表达式: {
            return .检查全局选择常量表达式((cast(选择常量表达式_)(表达式)), Ty);
        }
        default: break;
    }
}
void 检查表达式(节点_ 表达式, 节点_ 类型) {
    .检查源文件元素(类型);
    类型_ Ty = .获取类型节点的类型(类型);
    if (Ty.种类 == TypeID_.FunctionTyID) {
        .错误(类型, 诊断集_.functions_are_not_values_refer_to_them_as_pointers);
    }
    .检查表达式2(表达式, Ty);
}
void 检查函数声明(函数声明_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    Function FV = .检查函数头(n);
    .设置解析值(n, FV);
}
ThreadLocalMode_ 检查本地线程设置(本地线程设置_ n = ··null!(本地线程设置_)) {
    if (n is ··null!(本地线程设置_)) {
        return ThreadLocalMode_.NotThreadLocal;
    }
    节点_ 值 = n.值;
    switch (值.目标种类) {
        case ISK.localdynamic: {
            return ThreadLocalMode_.LocalDynamicTLSModel;
        }
        case ISK.initialexec: {
            return ThreadLocalMode_.InitialExecTLSModel;
        }
        case ISK.localexec: {
            return ThreadLocalMode_.LocalExecTLSModel;
        }
        default: break;
    }
    return ThreadLocalMode_.NotThreadLocal;
}
void 检查全局变量声明(全局变量声明_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    LinkageTypes Linkage = .检查链接特性(n);
    bool DSOLocal = .检查运行时抢占(n);
    VisibilityTypes Visibility = .检查可见性(n);
    DLLStorageClassTypes DLLStorageClass = .检查DLL储存类(n);
    .检查源文件元素(n.未命名的地址);
    ThreadLocalMode_ TLM = .检查本地线程设置(n.本地线程设置);
    UnnamedAddr unnamedAddr = UnnamedAddr.None;
    if (n.未命名的地址 !is ··null!(节点_)) {
        if (n.未命名的地址.目标种类 == ISK.unnamed_addr) {
            unnamedAddr = UnnamedAddr.Global;
        }
        else if (n.未命名的地址.目标种类 == ISK.local_unnamed_addr) {
            unnamedAddr = UnnamedAddr.Local;
        }
        else {
            .错误(n.未命名的地址, 诊断集_.未知指令_0, 获取节点的文本(n));
        }
    }
    if (!.isValidVisibilityForLinkage(Visibility, Linkage)) {
    }
    .检查源文件元素(n.对齐设置);
    Align_ Alignment = new Align_();
    if (n.对齐设置 !is ··null!(节点_)) {
        Alignment = .有解析值!(对齐值_)(n.对齐设置).Val;
    }
    .检查源文件元素(n.地址空间);
    uint AddrSpace;
    if (n.地址空间 !is ··null!(节点_)) {
        地址值_ 地址 = .有解析值!(地址值_)(n.地址空间);
        AddrSpace = 地址.Val;
    }
    else {
        AddrSpace = DataLayout_.s·getProgramAddressSpace(.当前布局);
    }
    bool IsExternallyInitialized = (n.外部初始化 !is ··null!(节点_));
    bool IsConstant = (n.全局或常量 !is ··null!(节点_)) && n.全局或常量.目标种类 == ISK.constant;
    .检查源文件元素(n.类型);
    类型_ Ty = .获取类型节点的类型(n.类型);
    .检查源文件元素(n.初始化);
    Constant Init;
    if (n.初始化 !is ··null!(节点_)) {
        Init = .有解析值!(Constant)(n.初始化);
    }
    if (.isFunctionTy(Ty) || !PTy_.s·isValidElementType(Ty)) {
        .错误(n.类型, 诊断集_.a0_, "invalid type for global variable"d);
    }
    dstring Section = ""d;
    if (n.段设置 !is ··null!(节点_)) {
        assert(n.段设置.目标种类 == ISK.文本字面量, "段设置错误"c);
        IR文本字面量_ 段 = (cast(IR文本字面量_)(n.段设置));
        Section = 段.内容;
    }
    dstring Partition = ""d;
    if (n.隔板设置 !is ··null!(节点_)) {
        assert(n.隔板设置.目标种类 == ISK.文本字面量, "隔板设置错误"c);
        IR文本字面量_ 隔板 = (cast(IR文本字面量_)(n.隔板设置));
        Partition = 隔板.内容;
    }
    封装值_ C;
    dstring 封装值 = ""d;
    if (n.函数封装 !is ··null!(节点_)) {
        封装设置_ 封装 = (cast(封装设置_)(n.函数封装));
        if (封装.值 !is ··null!(节点_)) {
            封装值 = (cast(IR文本字面量_)(封装.值)).内容;
        }
        else if (n.name !is ··null!(··IR节点_.IR标识符_)) {
            封装值 = n.name.内容;
        }
        else {
            .错误(n.函数封装, 诊断集_.a0_, "未知封装"d);
        }
        assert(封装值 !is ··null!(dstring), "封装值设置错误"c);
        符号_ s = .解析函数封装引用符号(封装, 封装值);
        if (s is ··null!(符号_)) {
            .错误(n.函数封装, 诊断集_.未定义的全局值);
        }
        else {
            Value t = .获取符号声明值(s);
            C = (cast(封装值_)(t));
        }
    }
    特性组_[] 特性组 = 创建数组!(特性组_)();
    特性组_ 函数特性 = .检查特性组(n.函数特性);
    if (函数特性 !is ··null!(特性组_)) {
        特性组.length = 1;
        特性组[0] = 函数特性;
    }
    GlobalVariable GV = new GlobalVariable();
    GV.ValueType = Ty;
    GV.类型 = TGet_.s·PtrTy_get(Ty, AddrSpace);
    GV.isConstantGlobal = IsConstant;
    GV.isExternallyInitializedConstant = IsExternallyInitialized;
    GV.Visibility = Visibility;
    GV.Align = Alignment;
    GV.AddrSpace = AddrSpace;
    GV.UnnamedAddrVal = unnamedAddr;
    GV.Section = Section;
    GV.ObjComdat = C;
    GV.Partition = Partition;
    GV.DllStorageClass = DLLStorageClass;
    GV.TLM = TLM;
    if (Init !is ··null!(Constant)) {
        GV.Ops.length = 1;
        GV.Ops[0] = Init;
    }
    GV.特性组 = 特性组;
    .设置解析值(n, GV);
}
void 检查别名声明(别名声明_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    bool IsAlias = n.别名令牌.目标种类 == ISK.alias_;
    LinkageTypes Linkage = .检查链接特性(n);
    bool DSOLocal = .检查运行时抢占(n);
    VisibilityTypes Visibility = .检查可见性(n);
    DLLStorageClassTypes DLLStorageClass = .检查DLL储存类(n);
    ThreadLocalMode_ TLM = .检查本地线程设置(n.本地线程设置);
    UnnamedAddr unnamedAddr = UnnamedAddr.None;
    if (n.未命名的地址 !is ··null!(节点_)) {
        if (n.未命名的地址.目标种类 == ISK.unnamed_addr) {
            unnamedAddr = UnnamedAddr.Global;
        }
        else if (n.未命名的地址.目标种类 == ISK.local_unnamed_addr) {
            unnamedAddr = UnnamedAddr.Local;
        }
        else {
            .错误(n.未命名的地址, 诊断集_.未知指令_0, 获取节点的文本(n));
        }
    }
    if (!.isValidVisibilityForLinkage(Visibility, Linkage)) {
        节点_ err = n.可见性 ? n.可见性 : n.连接特性 ? n.连接特性 : n.name ? n.name : n;
        .错误(err, 诊断集_.symbol_with_local_linkage_must_have_default_visibility);
    }
    .检查源文件元素(n.类型);
    类型_ Ty = .获取类型节点的类型(n.类型);
    节点_ 表达式 = n.表达式;
    Constant Aliasee;
    全局表达式_ GVE = (cast(全局表达式_)(表达式));
    if (GVE !is ··null!(全局表达式_)) {
        .检查源文件元素(GVE);
        Aliasee = .有解析值!(Constant)(GVE);
    }
    else {
        .检查ValID(GVE);
        Aliasee = .有解析值!(Constant)(GVE);
    }
    类型_ AliaseeType = Aliasee.类型;
    指针类型_ PTy = .dyn_cast!(指针类型_)(AliaseeType);
    if (PTy is ··null!(指针类型_)) {
        .错误(n.表达式, 诊断集_.a0_, "An alias or ifunc must have pointer type"d);
    }
    uint AddrSpace = PTy.地址;
    if (IsAlias && Ty != PTy.类型) {
        .错误(n.表达式, 诊断集_.a0_, "explicit pointee type doesn't match operand's pointee type"d);
    }
    if (!IsAlias && !.isFunctionTy(PTy.类型)) {
        .错误(n.表达式, 诊断集_.a0_, "explicit pointee type should be a function type"d);
    }
    dstring Partition = ""d;
    if ((n.隔板组 !is null) && (n.隔板组.原型 !is ··null!(节点_[]))) {
        foreach (节点_ par; n.隔板组) {
            IR文本字面量_ 隔板 = (cast(IR文本字面量_)(par));
            Partition = 隔板.内容;
        }
    }
    if (IsAlias) {
        GlobalAlias I = InstC_.s·GlobalAlias_C(Ty, AddrSpace, Linkage, Aliasee, TLM, Visibility, DLLStorageClass, unnamedAddr, DSOLocal, Partition);
        .设置解析值(n, I);
    }
    else {
        GlobalIFunc I = InstC_.s·GlobalIFunc_C(Ty, AddrSpace, Linkage, Aliasee, TLM, Visibility, DLLStorageClass, unnamedAddr, DSOLocal, Partition);
        .设置解析值(n, I);
    }
}
void 检查封装声明(封装声明_ n) {
    .获取符号声明值(n.符号);
}
void 检查独立元数据(独立元数据_ n) {
}
void 检查元数据声明(元数据声明_ n) {
}
特性组_ 检查特性组(基础节点.节点数组_!(节点_) ns = ··null!(基础节点.节点数组_!(节点_))) {
    if ((ns is null) || (ns.原型 is ··null!(节点_[]))) {
        return ··null!(特性组_);
    }
    特性组_ attrs = new 特性组_();
    foreach (节点_ n; ns) {
        if (n.目标种类 == ISK.标识符) {
            .合并特性组(attrs, .获取特性引用的特性组((cast(标识符_)(n))));
            continue;
        }
        .设置特性到特性组(attrs, .检查特性设置(n));
    }
    return attrs;
}
特性_ 检查特性设置(节点_ n) {
    Value link = .有解析值!(Value)(n);
    if (link !is ··null!(Value)) {
        return (cast(特性_)(link));
    }
    特性_ 特性;
    switch (n.目标种类) {
        case ISK.自定义特性设置: {
            IR文本字面量_ 键 = (cast(自定义特性设置_)(n)).键;
            dstring 键内容 = (cast(IR文本字面量_)(键)).内容;
            节点_ 值 = (cast(自定义特性设置_)(n)).值;
            dstring 内容 = (cast(IR文本字面量_)(值)).内容;
            文本特性_ l = new 文本特性_();
            l.键 = 键内容;
            l.值 = 内容;
            .设置解析值(n, l);
            return l;
        }
        case ISK.按引用设置:
        case ISK.结构引用设置:
        case ISK.预分配设置:
        case ISK.在内部分配设置:
        case ISK.按值设置: {
            AttrKind_ 键 = .获取需要类型特性键(n.目标种类);
            节点_ 值 = (cast(设置型节点_)(n)).值;
            类型_ Ty = .获取类型节点的类型(值);
            类型特性_ l = new 类型特性_();
            l.键 = 键;
            l.值 = Ty;
            .设置解析值(n, l);
            return l;
        }
        case ISK.倍数范围设置: {
            AttrKind_ 键 = .获取整数值特性键(n.目标种类);
            节点_ 值 = (cast(设置型节点_)(n)).值;
            IR数字字面量_ V0 = (cast(倍数范围设置内容_)(值)).最小;
            IR数字字面量_ V1 = (cast(倍数范围设置内容_)(值)).最大;
            if (V1 is ··null!(IR数字字面量_)) {
                V1 = V0;
            }
            ulong V0N = V0.整数值 << 32;
            ulong V1N = V1.整数值;
            ulong 整数值 = V0N | V1N;
            整数特性_ l = new 整数特性_();
            l.键 = 键;
            l.值 = 整数值;
            .设置解析值(n, l);
            return l;
        }
        case ISK.分配大小设置: {
            AttrKind_ 键 = .获取整数值特性键(n.目标种类);
            节点_ 值 = (cast(设置型节点_)(n)).值;
            IR数字字面量_ V0 = (cast(分配大小设置内容_)(值)).基本大小;
            IR数字字面量_ V1 = (cast(分配大小设置内容_)(值)).数量;
            ulong V0N = V0.整数值 << 32;
            uint V1N = V1 ? (cast(uint)(V1.整数值)) : (cast(uint)(-1));
            ulong 整数值 = V0N | V1N;
            整数特性_ l = new 整数特性_();
            l.键 = 键;
            l.值 = 整数值;
            .设置解析值(n, l);
            return l;
        }
        case ISK.对齐堆栈设置:
        case ISK.对齐设置: {
            AttrKind_ 键 = .获取整数值特性键(n.目标种类);
            节点_ 值 = (cast(设置型节点_)(n)).值;
            ulong 整数值 = (cast(IR数字字面量_)(值)).整数值;
            Align_ Align = new Align_(整数值);
            对齐特性_ l = new 对齐特性_();
            l.键 = 键;
            l.值 = Align;
            .设置解析值(n, l);
            return l;
        }
        case ISK.不可引用的设置:
        case ISK.不可引用的或空设置: {
            AttrKind_ 键 = .获取整数值特性键(n.目标种类);
            节点_ 值 = (cast(设置型节点_)(n)).值;
            ulong 整数值 = (cast(IR数字字面量_)(值)).整数值;
            整数特性_ l = new 整数特性_();
            l.键 = 键;
            l.值 = 整数值;
            .设置解析值(n, l);
            return l;
        }
        default: break;
    }
    AttrKind_ kind = .tokenToAttribute(n.目标种类);
    if (kind != AttrKind_.None) {
        枚举特性_ l = new 枚举特性_();
        l.值 = kind;
        .设置解析值(n, l);
        return l;
    }
    else {
        .错误(n, 诊断集_.未知特性_0, 获取节点的文本(n));
        枚举特性_ l = new 枚举特性_();
        l.值 = kind;
        .设置解析值(n, l);
        return l;
    }
}
void 检查特性声明(特性声明_ n) {
    循环每个!(节点_, 特性_)(n.成员, (节点_ n, size_t _) { return .检查特性设置(n); });
}
void 检查全局摘要声明(全局摘要声明_ n) {
}
void 检查模块级汇编(模块级汇编_ n) {
}
void 检查实参表达式(实参表达式_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    节点_ 表达式 = n.表达式;
    if (表达式.目标种类 == ISK.三点号) {
        ParamInfo Pinfo = new ParamInfo(n);
        .设置解析值(n, Pinfo);
    }
    else {
        基础节点.节点数组_!(节点_) 参数特性 = n.参数特性;
        特性组_ 特性组 = .检查特性组(n.参数特性);
        .检查源文件元素(表达式);
        Value V = .有解析值!(Value)(表达式);
        ParamInfo Pinfo = new ParamInfo(n, V, 特性组);
        .设置解析值(n, Pinfo);
    }
}
void 检查形参声明(形参声明_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    if (n.目标种类 == ISK.三点号) {
        三点值_ pn = new 三点值_();
        .设置解析值(n, pn);
        return;
    }
    .检查源文件元素(n.类型);
    类型_ Ty = .获取类型节点的类型(n.类型);
    特性组_ 特性组 = .检查特性组(n.形参特性);
    if (!.isValidArgumentType(Ty)) {
        .错误(n.类型, 诊断集_.argument_can_not_have_void_type);
    }
    (cast(符号_)(n.符号)).类型 = Ty;
    Argument V = new Argument();
    V.特性组 = 特性组;
    V.类型 = Ty;
    .设置解析值(n, V);
}
void 检查局部变量声明(局部变量声明_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    节点_ 初始化 = n.初始化;
    .检查指令语句(初始化);
    Value V = .有解析值!(Value)(初始化);
    if (V is ··null!(Value)) {
        .错误(n.初始化, 诊断集_.未定义的值);
    }
    .设置解析值(n, V);
}
void 检查分配指令(分配指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return // AllocaInst;
        ;
    }
    // AllocaInst;
    .检查源文件元素(n.IsInAlloca);
    bool IsInAlloca = ((n.IsInAlloca) !is ··null!(节点_));
    .检查源文件元素(n.IsSwiftError);
    bool IsSwiftError = ((n.IsSwiftError) !is ··null!(节点_));
    .检查源文件元素(n.类型);
    类型_ Ty = .获取类型节点的类型(n.类型);
    .检查源文件元素(n.AddrSpace);
    uint AddrSpace = 0;
    if (n.AddrSpace !is ··null!(节点_)) {
        AddrSpace = .有解析值!(地址值_)(n.AddrSpace).Val;
    }
    Align_ 对齐;
    .检查源文件元素(n.Alignment);
    if (n.Alignment !is ··null!(节点_)) {
        对齐值_ Alignment = .有解析值!(对齐值_)(n.Alignment);
        对齐 = Alignment.Val;
    }
    else {
        if (!TY_.s·isSized(Ty)) {
            .错误(n.类型, 诊断集_.a0_unsized_types_is_not_allowed, "alloca"d);
        }
        对齐 = DataLayout_.s·getPrefTypeAlign(.当前布局, Ty);
    }
    .检查源文件元素(n.Size);
    Value Size;
    if (n.Size !is ··null!(节点_)) {
        Size = .有解析值!(Value)(n.Size);
    }
    else {
        Size = CGet_.s·CInt_get(TGet_.s·IntTy_get(32), 1, false);
    }
    if ((n.尾部数据 !is null) && (n.尾部数据.原型 !is ··null!(节点_[]))) {
        foreach (节点_ tn; n.尾部数据) {
            .检查源文件元素(tn);
        }
    }
    AllocaInst I = InstC_.s·Alloca_C(Ty, AddrSpace, Size, 对齐, IsInAlloca, IsSwiftError);
    .设置解析值(n, I);
}
/// Create a result type for fcmp/icmp
类型_ makeCmpResultType(类型_ opnd_type) {
    向量类型_ Vt = .dyn_cast!(向量类型_)(opnd_type);
    if (Vt !is ··null!(向量类型_)) {
        return TGet_.s·VTy_get(.Int1Ty, VTy_.s·getElementCount(Vt));
    }
    return .Int1Ty;
}
void 检查加载指令(加载指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查源文件元素(n.isAtomic);
    bool isAtomic = ((n.isAtomic) !is ··null!(节点_));
    .检查源文件元素(n.isVolatile);
    bool isVolatile = ((n.isVolatile) !is ··null!(节点_));
    .检查源文件元素(n.Alignment);
    .检查源文件元素(n.类型);
    类型_ Ty = .获取类型节点的类型(n.类型);
    .检查源文件元素(n.表达式);
    Value Val = .有解析值!(Value)(n.表达式);
    if (!.isPointerTy(Val.类型) || !.isFirstClassType(Ty)) {
        节点_ err = !.isPointerTy(Val.类型) ? n.表达式.类型 : n.类型;
        .错误(err, 诊断集_.a0_operand_must_be_a_pointer_to_a_first_class_type, "load"d);
    }
    .检查源文件元素(n.同步);
    ubyte 同步_ = 1;
    if (n.同步 !is ··null!(同步范围设置_)) {
        同步值_ ssid = .有解析值!(同步值_)(n.同步);
        同步_ = ssid.Val;
    }
    AtomicOrdering_ 排序 = ISK转AtomicOrdering(n.排序);
    Align_ 对齐;
    if (n.Alignment !is ··null!(节点_)) {
        对齐值_ Alignment = .有解析值!(对齐值_)(n.Alignment);
        对齐 = Alignment.Val;
    }
    else {
        if (!TY_.s·isSized(Ty)) {
            .错误(n.类型, 诊断集_.a0_unsized_types_is_not_allowed, "load"d);
        }
        if (isAtomic) {
            .错误(n.isAtomic, 诊断集_.atomic_load_must_have_explicit_non_zero_alignment);
        }
        对齐 = DataLayout_.s·getPrefTypeAlign(.当前布局, Ty);
    }
    if (排序 == AtomicOrdering_.Release || 排序 == AtomicOrdering_.AcquireRelease) {
        .错误(n.排序, 诊断集_.atomic_load_cannot_use_Release_ordering);
    }
    指针类型_ pty = (cast(指针类型_)(Val.类型));
    if ((pty is ··null!(指针类型_)) || !PTy_.s·isOpaqueOrPointeeTypeMatches(pty, Ty)) {
        .错误(n.表达式.类型, 诊断集_.类型不匹配);
    }
    LoadInst I = InstC_.s·Load_C(Ty, Val, isVolatile, 对齐, 排序, 同步_);
    .设置解析值(n, I);
}
void 检查储存指令(储存指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查源文件元素(n.isAtomic);
    bool isAtomic = ((n.isAtomic) !is ··null!(节点_));
    .检查源文件元素(n.isVolatile);
    bool isVolatile = ((n.isVolatile) !is ··null!(节点_));
    .检查源文件元素(n.Alignment);
    .检查源文件元素(n.值0);
    Value Val = .有解析值!(Value)(n.值0);
    .检查源文件元素(n.值1);
    Value Ptr = .有解析值!(Value)(n.值1);
    if (!.isPointerTy(Ptr.类型)) {
        节点_ err = n.值1.类型;
        .错误(err, 诊断集_.a0_operand_must_be_a_pointer_to_a_first_class_type, "store"d);
    }
    if (!.isFirstClassType(Val.类型)) {
        .错误(n.值0.类型, 诊断集_.a0_operand_must_be_a_first_class_value, "store"d);
    }
    指针类型_ p = (cast(指针类型_)(Ptr.类型));
    if ((p is ··null!(指针类型_)) || !PTy_.s·isOpaqueOrPointeeTypeMatches(p, Val.类型)) {
        .错误(n.值0.类型, 诊断集_.类型不匹配);
    }
    Align_ 对齐;
    if (n.Alignment !is ··null!(节点_)) {
        对齐值_ Alignment = .有解析值!(对齐值_)(n.Alignment);
        对齐 = Alignment.Val;
    }
    else {
        if (!TY_.s·isSized(Val.类型)) {
            .错误(n.值0.类型, 诊断集_.a0_unsized_types_is_not_allowed, "store"d);
        }
        对齐 = DataLayout_.s·getPrefTypeAlign(.当前布局, Val.类型);
    }
    .检查源文件元素(n.同步);
    ubyte 同步_ = 1;
    if (n.同步 !is ··null!(同步范围设置_)) {
        同步值_ ssid = .有解析值!(同步值_)(n.同步);
        同步_ = ssid.Val;
    }
    AtomicOrdering_ 排序 = ISK转AtomicOrdering(n.排序);
    if (排序 == AtomicOrdering_.Release || 排序 == AtomicOrdering_.AcquireRelease) {
        .错误(n.排序, 诊断集_.atomic_load_cannot_use_Release_ordering);
    }
    LoadInst I = InstC_.s·Store_C(.VoidTy, Val, Ptr, isVolatile, 对齐, 排序, 同步_);
    .设置解析值(n, I);
}
void 检查转换类指令(转换类指令_ n) {
    InstructionKind_ Opc = ISK转为CastOpc(n.指令.目标种类);
    .检查源文件元素(n.左值);
    Value Op = .有解析值!(Value)(n.左值);
    .检查源文件元素(n.目标类型);
    类型_ DestTy = .获取类型节点的类型(n.目标类型);
    if (!.castIsValid(Opc, Op.类型, DestTy)) {
        .错误(n.左值, 诊断集_.a0_, "是无效的转换类型"d);
    }
    Instruction I = InstC_.s·Cast_C(Opc, Op, DestTy);
    .设置解析值(n, I);
}
void 检查整数和差积及左移指令(整数和差积及左移指令_ n) {
    InstructionKind_ Opc = ISK转为二元运算指令(n.指令.目标种类);
    .检查源文件元素(n.左值);
    Value Op0 = .有解析值!(Value)(n.左值);
    .检查表达式(n.右值, (cast(值表达式_)(n.左值)).类型);
    Value Op1 = .有解析值!(Value)(n.右值);
    if ((n.快速标志 !is null) && (n.快速标志.原型 !is ··null!(节点_[]))) {
        循环每个!(节点_, void*)(n.快速标志, (节点_ v, size_t i) {
            .检查每个元素(v, i);
            return null;
        });
    }
    FastMathFlags_ FMF = FastMathFlags_.无效值_;
    if ((n.快速标志 !is null) && (n.快速标志.原型 !is ··null!(节点_[]))) {
        foreach (节点_ f; n.快速标志) {
            FMF |= ISK转为快速数学标志(f.目标种类);
        }
    }
    if (!.isIntOrIntVectorTy(Op0.类型)) {
        .错误(n.左值, 诊断集_.a0_, "值只能为整数类型或整数向量类型"d);
    }
    BinaryOperator I = InstC_.s·Binary_C(Opc, Op0, Op1, FMF);
    .设置解析值(n, I);
}
void 检查小数和差积及左移指令(小数和差积及左移指令_ n) {
    InstructionKind_ Opc = ISK转为二元运算指令(n.指令.目标种类);
    .检查源文件元素(n.左值);
    Value Op0 = .有解析值!(Value)(n.左值);
    .检查表达式(n.右值, (cast(值表达式_)(n.左值)).类型);
    Value Op1 = .有解析值!(Value)(n.右值);
    if ((n.快速标志 !is null) && (n.快速标志.原型 !is ··null!(节点_[]))) {
        循环每个!(节点_, void*)(n.快速标志, (节点_ v, size_t i) {
            .检查每个元素(v, i);
            return null;
        });
    }
    FastMathFlags_ FMF = FastMathFlags_.无效值_;
    if ((n.快速标志 !is null) && (n.快速标志.原型 !is ··null!(节点_[]))) {
        foreach (节点_ f; n.快速标志) {
            FMF |= ISK转为快速数学标志(f.目标种类);
        }
    }
    if (!.isFPOrFPVectorTy(Op0.类型)) {
        .错误(n.左值, 诊断集_.a0_, "值只能为浮点类型或浮点向量类型"d);
    }
    BinaryOperator I = InstC_.s·Binary_C(Opc, Op0, Op1, FMF);
    .设置解析值(n, I);
}
void 检查有无符号求商及右移指令(有无符号求商及右移指令_ n) {
    InstructionKind_ Opc = ISK转为二元运算指令(n.指令.目标种类);
    .检查源文件元素(n.左值);
    Value Op0 = .有解析值!(Value)(n.左值);
    .检查表达式(n.右值, (cast(值表达式_)(n.左值)).类型);
    Value Op1 = .有解析值!(Value)(n.右值);
    .检查源文件元素(n.快速标志);
    bool Exact = false;
    if (n.快速标志 !is ··null!(节点_)) {
        Exact = true;
    }
    if (!.isIntOrIntVectorTy(Op0.类型)) {
        .错误(n.左值, 诊断集_.a0_, "值只能为整数类型或整数向量类型"d);
    }
    BinaryOperator I = InstC_.s·Binary_C(Opc, Op0, Op1, FastMathFlags_.无效值_, Exact);
    .设置解析值(n, I);
}
void 检查有无符号求余数运算指令(有无符号求余数运算指令_ n) {
    InstructionKind_ Opc = ISK转为二元运算指令(n.指令.目标种类);
    .检查源文件元素(n.左值);
    Value Op0 = .有解析值!(Value)(n.左值);
    .检查表达式(n.右值, (cast(值表达式_)(n.左值)).类型);
    Value Op1 = .有解析值!(Value)(n.右值);
    if (!.isIntOrIntVectorTy(Op0.类型)) {
        .错误(n.左值, 诊断集_.a0_, "值只能为整数类型或整数向量类型"d);
    }
    BinaryOperator I = InstC_.s·Binary_C(Opc, Op0, Op1);
    .设置解析值(n, I);
}
void 检查位运算指令(位运算指令_ n) {
    InstructionKind_ Opc = ISK转为二元运算指令(n.指令.目标种类);
    .检查源文件元素(n.左值);
    Value Op0 = .有解析值!(Value)(n.左值);
    .检查表达式(n.右值, (cast(值表达式_)(n.左值)).类型);
    Value Op1 = .有解析值!(Value)(n.右值);
    if (!.isIntOrIntVectorTy(Op0.类型)) {
        .错误(n.左值, 诊断集_.a0_, "值只能为整数类型或整数向量类型"d);
    }
    BinaryOperator I = InstC_.s·Binary_C(Opc, Op0, Op1);
    .设置解析值(n, I);
}
void 检查比较运算指令(比较运算指令_ n) {
    InstructionKind_ Opc = ISK转为比较运算符(n.指令.目标种类);
    .检查源文件元素(n.副词);
    CmpInst_Predicate_ pred = ISK转为CmpInst_Predicate(n.副词.目标种类);
    .检查源文件元素(n.左值);
    Value Op0 = .有解析值!(Value)(n.左值);
    .检查表达式(n.右值, (cast(值表达式_)(n.左值)).类型);
    FastMathFlags_ FMF = FastMathFlags_.无效值_;
    if ((n.快速标志 !is null) && (n.快速标志.原型 !is ··null!(节点_[]))) {
        foreach (节点_ f; n.快速标志) {
            FMF |= ISK转为快速数学标志(f.目标种类);
        }
    }
    Value Op1 = .有解析值!(Value)(n.右值);
    if (Opc == InstructionKind_.FCmp) {
        if (!.isFPOrFPVectorTy(Op0.类型)) {
            .错误(n.左值, 诊断集_.a0_, "值只能为浮点类型或浮点向量类型"d);
        }
    }
    else {
        if (!.isIntOrIntVectorTy(Op0.类型) && !.isPtrOrPtrVectorTy(Op0.类型)) {
            .错误(n.左值, 诊断集_.a0_, "icmp requires integer operands"d);
        }
    }
    CmpInst I = InstC_.s·Cmp_C(Opc, pred, Op0, Op1, FMF);
    .设置解析值(n, I);
}
void 检查取反指令(取反指令_ n) {
    .检查源文件元素(n.运算数);
    Value Op0 = .有解析值!(Value)(n.运算数);
    FastMathFlags_ FMF = FastMathFlags_.无效值_;
    if ((n.快速标志 !is null) && (n.快速标志.原型 !is ··null!(节点_[]))) {
        foreach (节点_ f; n.快速标志) {
            FMF |= ISK转为快速数学标志(f.目标种类);
        }
    }
    if (!.isFPOrFPVectorTy(Op0.类型)) {
        .错误(n.运算数, 诊断集_.a0_, "值只能为浮点类型或浮点向量类型"d);
    }
    UnaryOperator I = InstC_.s·Unary_C(InstructionKind_.FNeg, Op0, FMF);
    .设置解析值(n, I);
}
void 检查不及指令(不及指令_ n) {
    UnreachableInst I = new UnreachableInst(.VoidTy);
    .设置解析值(n, I);
}
void 检查返回指令(返回指令_ n) {
    .检查源文件元素(n.表达式);
    Value V;
    if (n.表达式 !is ··null!(值表达式_)) {
        V = .有解析值!(Value)(n.表达式);
    }
    RetInst I = InstC_.s·Ret_C(V);
    .设置解析值(n, I);
}
void 检查跳转指令(跳转指令_ n) {
    .检查源文件元素(n.条件);
    .检查源文件元素(n.为真);
    .检查源文件元素(n.为假);
    if (n.条件 is ··null!(值表达式_)) {
        assert(n.为假 is ··null!(值表达式_), "缺少假目标"c);
        BasicBlock IfTrue = .有解析值!(BasicBlock)(n.为真);
        if (IfTrue is ··null!(BasicBlock)) {
            .错误(n.为真, 诊断集_.a0_, "未定义的基本块"d);
        }
        BranchInst I = InstC_.s·Branch_C(IfTrue);
        .设置解析值(n, I);
    }
    else {
        assert((n.条件 !is ··null!(值表达式_)) && (n.为假 !is ··null!(值表达式_)), "错误的跳转语句"c);
        BasicBlock IfTrue = .有解析值!(BasicBlock)(n.为真);
        if (IfTrue is ··null!(BasicBlock)) {
            .错误(n.为真, 诊断集_.a0_, "未定义的基本块"d);
        }
        BasicBlock IfFalse = .有解析值!(BasicBlock)(n.为假);
        if (IfFalse is ··null!(BasicBlock)) {
            .错误(n.为假, 诊断集_.a0_, "未定义的基本块"d);
        }
        Value Cond = .有解析值!(Value)(n.条件);
        if (Cond is ··null!(Value)) {
            .错误(n.条件, 诊断集_.a0_, "未定义值"d);
        }
        if (Cond.类型 != .Int1Ty) {
            .错误(n.条件.类型, 诊断集_.a0_, "branch condition must have 'i1' type"d);
        }
        BranchInst I = InstC_.s·Branch_C(IfTrue, IfFalse, Cond);
        .设置解析值(n, I);
    }
}
void 检查假如指令(假如指令_ n) {
    .检查源文件元素(n.条件);
    Value Cond = .有解析值!(Value)(n.条件);
    if ((Cond is ··null!(Value)) || !.isIntegerTy(Cond.类型)) {
        .错误(n.条件, 诊断集_.a0_, "switch condition must have integer type"d);
    }
    .检查源文件元素(n.标签);
    BasicBlock DefaultBB = .有解析值!(BasicBlock)(n.标签);
    if (DefaultBB is ··null!(BasicBlock)) {
        .错误(n.标签, 诊断集_.a0_, "未定义的默认块"d);
    }
    词典_!(Value) SeenCases = new 词典_!(Value)();
    跳转表_[] Table = 创建数组!(跳转表_)();
    foreach (跳转表元素_ T; n.跳转表) {
        .检查源文件元素(T.条件);
        ConstantInt Constant = .有解析值!(ConstantInt)(T.条件);
        if ((Constant is ··null!(ConstantInt)) || !.isConstantInt(Constant)) {
            .错误(T.条件, 诊断集_.a0_, "case value is not a constant integer"d);
        }
        else {
            dstring IK = ·to!(dstring)(Constant.toHash());
            if (SeenCases.具有(IK)) {
                .错误(T.条件, 诊断集_.a0_, "duplicate case value in switch"d);
            }
            else {
                SeenCases.p·设置(IK, Constant);
            }
        }
        .检查源文件元素(T.标签);
        BasicBlock DestBB = .有解析值!(BasicBlock)(n.标签);
        .追加!(跳转表_)(Table, new 跳转表_(Constant, DestBB));
    }
    SwitchInst I = InstC_.s·Switch_C(Cond, DefaultBB, Table);
    .设置解析值(n, I);
}
void 检查直接跳转指令(直接跳转指令_ n) {
    .检查源文件元素(n.值);
    Value Address = .有解析值!(Value)(n.值);
    if ((Address is ··null!(Value)) || !.isPointerTy(Address.类型)) {
        .错误(n.值, 诊断集_.a0_, "Address of indirectbr must be a pointer"d);
    }
    BasicBlock[] DestList = 创建数组!(BasicBlock)();
    foreach (值表达式_ T; n.跳转表) {
        .检查源文件元素(T);
        BasicBlock DestBB = .有解析值!(BasicBlock)(T);
        .追加!(BasicBlock)(cast(BasicBlock[])(DestList), DestBB);
    }
    IndirectBrInst I = InstC_.s·IndirectBr_C(Address, DestList);
    .设置解析值(n, I);
}
void 检查唤出指令(唤出指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查源文件元素(n.返回类型);
    类型_[] ParamTypes = 创建数组!(类型_)();
    特性组_[] ArgAttrs = 创建数组!(特性组_)();
    ParamInfo[] ArgList = 创建数组!(ParamInfo)();
    Value[] Args = 创建数组!(Value)();
    if ((n.实参列表 !is null) && (n.实参列表.原型 !is ··null!(节点_[]))) {
        {
            for (int i = 0; i < n.实参列表.length; ++i) {
                节点_ arg = n.实参列表[i];
                .检查源文件元素(arg);
                ParamInfo AV = .有解析值!(ParamInfo)(arg);
                .追加!(ParamInfo)(ArgList, AV);
                if ((AV !is ··null!(ParamInfo)) && (AV.V !is ··null!(Value))) {
                    .追加!(Value)(Args, AV.V);
                    .追加!(类型_)(ParamTypes, AV.V.类型);
                }
                if (AV.Attrs !is ··null!(特性组_)) {
                    .追加!(特性组_)(ArgAttrs, AV.Attrs);
                }
            }
        }
    }
    类型_ RetType = .获取类型节点的类型(n.返回类型);
    函数类型_ Ty = .dyn_cast!(函数类型_)(RetType);
    if (Ty is ··null!(函数类型_)) {
        if (!.isValidReturnType(RetType)) {
            .错误(n.返回类型, 诊断集_.a0_, "Invalid result type for LLVM function"d);
        }
        Ty = TGet_.s·FuncTy_get(RetType, ParamTypes, false);
    }
    节点_ CalleeID = n.name;
    .检查ValID(n.name);
    Value ca = .有解析值!(Value)(n.name);
    if (ca is ··null!(Value)) {
        .错误(n.name, 诊断集_.a0_, "未知调用"d);
    }
    if ((ca !is ··null!(Value)) && ca.种类 == ValueTy_.InlineAsmVal) {
        (cast(InlineAsm)(ca)).FTy = Ty;
    }
    .检查源文件元素(n.地址空间);
    uint InvokeAddrSpace;
    if (n.地址空间 !is ··null!(地址空间设置_)) {
        地址值_ 地址 = .有解析值!(地址值_)(n.地址空间);
        InvokeAddrSpace = 地址.Val;
    }
    else {
        InvokeAddrSpace = DataLayout_.s·getProgramAddressSpace(.当前布局);
    }
    .检查表达式2(n.name, TGet_.s·PtrTy_get(Ty, InvokeAddrSpace));
    Value Callee = .有解析值!(Value)(n.name);
    特性组_ RetAttrs = .检查特性组(n.返回类型特性);
    特性组_ FnAttrs = .检查特性组(n.函数特性组);
    CallingConv_ CC = ISK转换调用约定(n.调用约定);
    .检查源文件元素(n.捆绑的操作数);
    BundleDef[] BundleList;
    if (n.捆绑的操作数 !is ··null!(操作数标签组_)) {
        BundleList = (cast(BundleDef[])(.有解析值!(BundleDefS)(n.捆绑的操作数).Ops));
    }
    .检查源文件元素(n.转到块);
    BasicBlock NormalBB = .有解析值!(BasicBlock)(n.转到块);
    .检查源文件元素(n.异常块);
    BasicBlock UnwindBB = .有解析值!(BasicBlock)(n.异常块);
    特性组_[] 特性组 = 创建数组!(特性组_)();
    .追加!(特性组_)(cast(特性组_[])(特性组), FnAttrs);
    .追加!(特性组_)(cast(特性组_[])(特性组), RetAttrs);
    .追加!(特性组_)(特性组, ArgAttrs);
    InvokeInst I = InstC_.s·Invoke_C(Ty, Callee, NormalBB, UnwindBB, Args, BundleList, 特性组, CC);
    .设置解析值(n, I);
}
void 检查重启指令(重启指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查值表达式(n.表达式);
    Value V = .有解析值!(Value)(n.表达式);
    ResumeInst I = InstC_.s·Resume_C(V);
    .设置解析值(n, I);
}
void 检查清理返回指令(清理返回指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查表达式2(n.起始块, .TokenTy);
    Value CleanupPad = .有解析值!(Value)(n.起始块);
    BasicBlock UnwindBB;
    if (n.目标块 !is ··null!(节点_)) {
        .检查源文件元素(n.目标块);
        UnwindBB = .有解析值!(BasicBlock)(n.目标块);
    }
    CleanupReturnInst I = InstC_.s·CleanupRet_C(CleanupPad, UnwindBB);
    .设置解析值(n, I);
}
void 检查捕获返回指令(捕获返回指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查表达式2(n.起始块, .TokenTy);
    Value CatchPad = .有解析值!(Value)(n.起始块);
    .检查源文件元素(n.目标块);
    BasicBlock BB = .有解析值!(BasicBlock)(n.目标块);
    CatchReturnInst I = InstC_.s·CatchRet_C(CatchPad, BB);
    .设置解析值(n, I);
}
void 检查捕获分支指令(捕获分支指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查表达式2(n.表达式, .TokenTy);
    Value ParentPad = .有解析值!(Value)(n.表达式);
    BasicBlock[] Table = 创建数组!(BasicBlock)();
    {
        for (int i = 0; i < n.地址表.length; ++i) {
            节点_ db = n.地址表[i];
            .检查源文件元素(db);
            BasicBlock DestBB = .有解析值!(BasicBlock)(db);
            .追加!(BasicBlock)(Table, DestBB);
        }
    }
    BasicBlock UnwindBB;
    if (n.展开标签 !is ··null!(节点_)) {
        .检查源文件元素(n.展开标签);
        UnwindBB = .有解析值!(BasicBlock)(n.展开标签);
    }
    CatchSwitchInst I = InstC_.s·CatchSwitch_C(ParentPad, Table, UnwindBB);
    .设置解析值(n, I);
}
void 检查调用跳转指令(调用跳转指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查源文件元素(n.返回类型);
    类型_[] ParamTypes = 创建数组!(类型_)();
    特性组_[] ArgAttrs = 创建数组!(特性组_)();
    ParamInfo[] ArgList = 创建数组!(ParamInfo)();
    Value[] Args = 创建数组!(Value)();
    if ((n.实参列表 !is null) && (n.实参列表.原型 !is ··null!(节点_[]))) {
        {
            for (int i = 0; i < n.实参列表.length; ++i) {
                节点_ arg = n.实参列表[i];
                .检查源文件元素(arg);
                ParamInfo AV = .有解析值!(ParamInfo)(arg);
                .追加!(ParamInfo)(ArgList, AV);
                if ((AV !is ··null!(ParamInfo)) && (AV.V !is ··null!(Value))) {
                    .追加!(Value)(Args, AV.V);
                    .追加!(类型_)(ParamTypes, AV.V.类型);
                }
                if (AV.Attrs !is ··null!(特性组_)) {
                    .追加!(特性组_)(ArgAttrs, AV.Attrs);
                }
            }
        }
    }
    类型_ RetType = .获取类型节点的类型(n.返回类型);
    函数类型_ Ty = .dyn_cast!(函数类型_)(RetType);
    if (Ty is ··null!(函数类型_)) {
        if (!.isValidReturnType(RetType)) {
            .错误(n.返回类型, 诊断集_.a0_, "Invalid result type for LLVM function"d);
        }
        Ty = TGet_.s·FuncTy_get(RetType, ParamTypes, false);
    }
    节点_ CalleeID = n.name;
    .检查ValID(n.name);
    Value ca = .有解析值!(Value)(n.name);
    if (ca is ··null!(Value)) {
        .错误(n.name, 诊断集_.a0_, "未知调用"d);
    }
    if ((ca !is ··null!(Value)) && ca.种类 == ValueTy_.InlineAsmVal) {
        (cast(InlineAsm)(ca)).FTy = Ty;
    }
    .检查源文件元素(n.地址空间);
    uint InvokeAddrSpace;
    if (n.地址空间 !is ··null!(地址空间设置_)) {
        地址值_ 地址 = .有解析值!(地址值_)(n.地址空间);
        InvokeAddrSpace = 地址.Val;
    }
    else {
        InvokeAddrSpace = DataLayout_.s·getProgramAddressSpace(.当前布局);
    }
    .检查表达式2(n.name, TGet_.s·PtrTy_get(Ty, InvokeAddrSpace));
    Value Callee = .有解析值!(Value)(n.name);
    特性组_ RetAttrs = .检查特性组(n.返回类型特性);
    特性组_ FnAttrs = .检查特性组(n.函数特性组);
    CallingConv_ CC = ISK转换调用约定(n.调用约定);
    .检查源文件元素(n.捆绑的操作数);
    BundleDef[] BundleList;
    if (n.捆绑的操作数 !is ··null!(操作数标签组_)) {
        BundleList = (cast(BundleDef[])(.有解析值!(BundleDefS)(n.捆绑的操作数).Ops));
    }
    .检查源文件元素(n.默认标签);
    BasicBlock DefaultDest = .有解析值!(BasicBlock)(n.默认标签);
    BasicBlock[] IndirectDests = 创建数组!(BasicBlock)();
    {
        for (int i = 0; i < n.转到块.length; ++i) {
            节点_ bb = n.转到块[i];
            .检查源文件元素(bb);
            BasicBlock DestBB = .有解析值!(BasicBlock)(bb);
            .追加!(BasicBlock)(IndirectDests, DestBB);
        }
    }
    特性组_[] 特性组 = 创建数组!(特性组_)();
    .追加!(特性组_)(cast(特性组_[])(特性组), FnAttrs);
    .追加!(特性组_)(cast(特性组_[])(特性组), RetAttrs);
    .追加!(特性组_)(特性组, ArgAttrs);
    CallBrInst I = InstC_.s·CallBr_C(Ty, Callee, DefaultDest, IndirectDests, Args, BundleList, 特性组, CC);
    .设置解析值(n, I);
}
void 检查清理场指令(清理场指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查表达式2(n.表达式, .TokenTy);
    Value ParentPad = .有解析值!(Value)(n.表达式);
    Value[] Args = 创建数组!(Value)();
    {
        for (int i = 0; i < n.异常参数.length; ++i) {
            节点_ earg = n.异常参数[i];
            .检查源文件元素(earg);
            Value a = .有解析值!(Value)(earg);
            .追加!(Value)(Args, a);
        }
    }
    CleanupPadInst I = InstC_.s·CleanupPad_C(ParentPad, Args);
    .设置解析值(n, I);
}
void 检查捕获场指令(捕获场指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查表达式2(n.表达式, .TokenTy);
    Value CatchSwitch = .有解析值!(Value)(n.表达式);
    Value[] Args = 创建数组!(Value)();
    {
        for (int i = 0; i < n.异常参数.length; ++i) {
            节点_ earg = n.异常参数[i];
            .检查源文件元素(earg);
            Value a = .有解析值!(Value)(earg);
            .追加!(Value)(Args, a);
        }
    }
    CatchPadInst I = InstC_.s·CatchPad_C(CatchSwitch, Args);
    .设置解析值(n, I);
}
void 检查可变参数指令(可变参数指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查源文件元素(n.值);
    Value Op = .有解析值!(Value)(n.值);
    .检查源文件元素(n.类型);
    类型_ EltTy = .获取类型节点的类型(n.类型);
    if (!.isFirstClassType(EltTy)) {
        .错误(n.类型, 诊断集_.a0_, "va_arg requires operand with first class type"d);
    }
    VAArgInst I = InstC_.s·VAArg_C(EltTy, Op);
    .设置解析值(n, I);
}
void 检查提取元素指令(提取元素指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查源文件元素(n.值0);
    Value Val = .有解析值!(Value)(n.值0);
    .检查源文件元素(n.值1);
    Value Index = .有解析值!(Value)(n.值1);
    if ((Val is ··null!(Value)) || (Index is ··null!(Value)) || !EEI_.s·isValidOperands(Val, Index)) {
        .错误(n.值0, 诊断集_.a0_, "invalid extractelement operands"d);
    }
    ExtractElementInst I = InstC_.s·ExtractElement_C(Val, Index);
    .设置解析值(n, I);
}
void 检查插入元素指令(插入元素指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查源文件元素(n.值0);
    Value Op1 = .有解析值!(Value)(n.值0);
    .检查源文件元素(n.值1);
    Value OP2 = .有解析值!(Value)(n.值1);
    .检查源文件元素(n.值2);
    Value OP3 = .有解析值!(Value)(n.值2);
    if ((Op1 is ··null!(Value)) || (OP2 is ··null!(Value)) || (OP3 is ··null!(Value)) || !IEI_.s·isValidOperands(Op1, OP2, OP3)) {
        .错误(n.值0, 诊断集_.a0_, "invalid insertelement operands"d);
    }
    InsertElementInst I = InstC_.s·InsertElement_C(Op1, OP2, OP3);
    .设置解析值(n, I);
}
void 检查洗牌向量指令(洗牌向量指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查源文件元素(n.值0);
    Value Op1 = .有解析值!(Value)(n.值0);
    .检查源文件元素(n.值1);
    Value OP2 = .有解析值!(Value)(n.值1);
    .检查源文件元素(n.值2);
    Constant OP3 = .有解析值!(Constant)(n.值2);
    if ((Op1 is ··null!(Value)) || (OP2 is ··null!(Value)) || (OP3 is ··null!(Constant)) || !SVI_.s·isValidOperands(Op1, OP2, OP3)) {
        .错误(n.值0, 诊断集_.a0_, "invalid shufflevector operands"d);
    }
    ShuffleVectorInst I = InstC_.s·ShuffleVector_C(Op1, OP2, OP3);
    .设置解析值(n, I);
}
void 检查PHI节点指令(PHI节点指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查源文件元素(n.类型);
    类型_ Ty = .获取类型节点的类型(n.类型);
    Value[] PHIVals = 创建数组!(Value)();
    {
        for (int i = 0; i < n.节点组.length; ++i) {
            PHI节点元素_ e = (cast(PHI节点元素_)(n.节点组[i]));
            .检查表达式2(e.左值, Ty);
            Value Op0 = .有解析值!(Value)(e.左值);
            .检查表达式2(e.右值, .LabelTy);
            BasicBlock Op1 = .有解析值!(BasicBlock)(e.右值);
            .追加!(Value)(cast(Value[])(PHIVals), Op0, Op1);
        }
    }
    if (!.isFirstClassType(Ty)) {
        .错误(n.类型, 诊断集_.a0_, "phi node must have first class type"d);
    }
    FastMathFlags_ FMF = FastMathFlags_.无效值_;
    if ((n.快速标志 !is null) && (n.快速标志.原型 !is ··null!(节点_[]))) {
        foreach (节点_ f; n.快速标志) {
            FMF |= ISK转为快速数学标志(f.目标种类);
        }
    }
    PHINode I = InstC_.s·PHINode_C(Ty, PHIVals, FMF);
    .设置解析值(n, I);
}
void 检查着陆场指令(着陆场指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查源文件元素(n.类型);
    类型_ Ty = .获取类型节点的类型(n.类型);
    bool Cleanup = false;
    if (n.清理指令 !is ··null!(节点_)) {
        assert(n.清理指令.目标种类 == ISK.cleanup, "xx"c);
        Cleanup = true;
    }
    Constant[] CVS = 创建数组!(Constant)();
    if ((n.捕获或过滤器 !is null) && (n.捕获或过滤器.原型 !is ··null!(捕获或过滤器_[]))) {
        {
            for (int i = 0; i < n.捕获或过滤器.length; ++i) {
                捕获或过滤器_ cf = (cast(捕获或过滤器_)(n.捕获或过滤器[i]));
                .检查源文件元素(cf.捕获_);
                Constant CV = .有解析值!(Constant)(cf.捕获_);
                if (CV is ··null!(Constant)) {
                    .错误(cf.捕获_, 诊断集_.a0_, "clause argument must be a constant"d);
                }
                else {
                    if (cf.指令.目标种类 == ISK.catch_) {
                        if (.isArrayType(CV.类型)) {
                            .错误(cf.指令, 诊断集_.a0_, "'catch' clause has an invalid type"d);
                        }
                    }
                    else {
                        assert(cf.指令.目标种类 == ISK.filter, "xx"c);
                        if (!.isArrayType(CV.类型)) {
                            .错误(cf.指令, 诊断集_.a0_, "'filter' clause has an invalid type"d);
                        }
                    }
                    .追加!(Constant)(CVS, CV);
                }
            }
        }
    }
    LandingPadInst I = InstC_.s·LandingPad_C(Ty, Cleanup, CVS);
    .设置解析值(n, I);
}
void 检查冻结指令(冻结指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查源文件元素(n.表达式);
    Value Op = .有解析值!(Value)(n.表达式);
    FreezeInst I = InstC_.s·Freeze_C(Op);
    .设置解析值(n, I);
}
void 检查调用指令(调用指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查源文件元素(n.返回类型);
    类型_[] ParamTypes = 创建数组!(类型_)();
    特性组_[] ArgAttrs = 创建数组!(特性组_)();
    ParamInfo[] ArgList = 创建数组!(ParamInfo)();
    Value[] Args = 创建数组!(Value)();
    if ((n.实参列表 !is null) && (n.实参列表.原型 !is ··null!(节点_[]))) {
        {
            for (int i = 0; i < n.实参列表.length; ++i) {
                节点_ arg = n.实参列表[i];
                .检查源文件元素(arg);
                ParamInfo AV = .有解析值!(ParamInfo)(arg);
                .追加!(ParamInfo)(ArgList, AV);
                if ((AV !is ··null!(ParamInfo)) && (AV.V !is ··null!(Value))) {
                    .追加!(Value)(Args, AV.V);
                    .追加!(类型_)(ParamTypes, AV.V.类型);
                }
                if (AV.Attrs !is ··null!(特性组_)) {
                    .追加!(特性组_)(ArgAttrs, AV.Attrs);
                }
            }
        }
    }
    类型_ RetType = .获取类型节点的类型(n.返回类型);
    函数类型_ Ty = .dyn_cast!(函数类型_)(RetType);
    if (Ty is ··null!(函数类型_)) {
        if (!.isValidReturnType(RetType)) {
            .错误(n.返回类型, 诊断集_.a0_, "Invalid result type for LLVM function"d);
        }
        Ty = TGet_.s·FuncTy_get(RetType, ParamTypes, false);
    }
    节点_ CalleeID = n.name;
    .检查ValID(n.name);
    Value ca = .有解析值!(Value)(n.name);
    if (ca is ··null!(Value)) {
        .错误(n.name, 诊断集_.a0_, "未知调用"d);
    }
    if ((ca !is ··null!(Value)) && ca.种类 == ValueTy_.InlineAsmVal) {
        (cast(InlineAsm)(ca)).FTy = Ty;
    }
    .检查源文件元素(n.地址空间);
    uint CallAddrSpace;
    if (n.地址空间 !is ··null!(地址空间设置_)) {
        地址值_ 地址 = .有解析值!(地址值_)(n.地址空间);
        CallAddrSpace = 地址.Val;
    }
    else {
        CallAddrSpace = DataLayout_.s·getProgramAddressSpace(.当前布局);
    }
    .检查表达式2(n.name, TGet_.s·PtrTy_get(Ty, CallAddrSpace));
    Value Callee = .有解析值!(Value)(n.name);
    特性组_ RetAttrs = .检查特性组(n.返回类型特性);
    特性组_ FnAttrs = .检查特性组(n.函数特性组);
    CallingConv_ CC = ISK转换调用约定(n.调用约定);
    .检查源文件元素(n.捆绑的操作数);
    BundleDef[] BundleList;
    if (n.捆绑的操作数 !is ··null!(操作数标签组_)) {
        BundleList = (cast(BundleDef[])(.有解析值!(BundleDefS)(n.捆绑的操作数).Ops));
    }
    特性组_[] 特性组 = 创建数组!(特性组_)();
    .追加!(特性组_)(cast(特性组_[])(特性组), FnAttrs);
    .追加!(特性组_)(cast(特性组_[])(特性组), RetAttrs);
    .追加!(特性组_)(特性组, ArgAttrs);
    TailCallKind_ Tck = ISK转尾调用标志(n.尾调用修饰符);
    FastMathFlags_ FMF = FastMathFlags_.无效值_;
    if ((n.快速标志 !is null) && (n.快速标志.原型 !is ··null!(节点_[]))) {
        foreach (节点_ f; n.快速标志) {
            FMF |= ISK转为快速数学标志(f.目标种类);
        }
    }
    CallInst I = InstC_.s·Call_C(Ty, Callee, Args, BundleList, 特性组, CC, FMF, Tck);
    .设置解析值(n, I);
}
void 检查原子修改内存按条件指令(原子修改内存按条件指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查源文件元素(n.值0);
    Value Ptr = .有解析值!(Value)(n.值0);
    .检查源文件元素(n.值0);
    Value Cmp = .有解析值!(Value)(n.值1);
    .检查源文件元素(n.值2);
    Value New = .有解析值!(Value)(n.值2);
    .检查源文件元素(n.同步);
    ubyte SSID = 1;
    if (n.同步 !is ··null!(同步范围设置_)) {
        同步值_ ssid = .有解析值!(同步值_)(n.同步);
        SSID = ssid.Val;
    }
    AtomicOrdering_ 真排序 = ISK转AtomicOrdering(n.真排序);
    AtomicOrdering_ 假排序 = ISK转AtomicOrdering(n.假排序);
    if (!.isValidSuccessOrdering(真排序) && (n.真排序 !is ··null!(节点_))) {
        .错误(n.真排序, 诊断集_.a0_, "invalid cmpxchg success ordering"d);
    }
    if (!.isValidFailureOrdering(假排序) && (n.假排序 !is ··null!(节点_))) {
        .错误(n.假排序, 诊断集_.a0_, "invalid cmpxchg failure ordering"d);
    }
    if (!.isPointerTy(Ptr.类型)) {
        .错误(n.值2, 诊断集_.a0_, "cmpxchg operand must be a pointer"d);
    }
    if (!PTy_.s·isOpaqueOrPointeeTypeMatches((cast(指针类型_)(Ptr.类型)), Cmp.类型)) {
        .错误(n.值2, 诊断集_.a0_, "compare value and pointer type do not match"d);
    }
    if (!PTy_.s·isOpaqueOrPointeeTypeMatches((cast(指针类型_)(Ptr.类型)), New.类型)) {
        .错误(n.值2, 诊断集_.a0_, "new value and pointer type do not match"d);
    }
    if (Cmp.类型 != New.类型) {
        .错误(n.值2, 诊断集_.a0_, "compare value and new value type do not match"d);
    }
    if (!.isFirstClassType(New.类型)) {
        .错误(n.值2, 诊断集_.a0_, "cmpxchg operand must be a first class value"d);
    }
    .检查源文件元素(n.Alignment);
    Align_ Alignment;
    if (n.Alignment !is ··null!(节点_)) {
        Alignment = .有解析值!(对齐值_)(n.Alignment).Val;
    }
    else {
        Alignment = new Align_(DataLayout_.s·getTypeStoreSize(.当前布局, Cmp.类型).Val);
    }
    bool isVolatile = ((n.isVolatile) !is ··null!(节点_));
    bool isWeak = ((n.isWeak) !is ··null!(节点_));
    AtomicCmpXchgInst I = InstC_.s·AtomicCmpXchg_C(Ptr, Cmp, New, Alignment, 真排序, 假排序, SSID, isVolatile, isWeak);
    .设置解析值(n, I);
}
bool isValidSuccessOrdering(AtomicOrdering_ or) {
    return or != AtomicOrdering_.NotAtomic && or != AtomicOrdering_.Unordered;
}
bool isValidFailureOrdering(AtomicOrdering_ or) {
    return or != AtomicOrdering_.NotAtomic && or != AtomicOrdering_.Unordered && or != AtomicOrdering_.AcquireRelease && or != AtomicOrdering_.Release;
}
void 检查原子修改内存指令(原子修改内存指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    AtomicRMWInstBinOp_ Operation = ISK转为AtomicRMWInstBinOp(n.运算);
    bool IsFP = Operation == AtomicRMWInstBinOp_.FAdd || Operation == AtomicRMWInstBinOp_.FSub;
    .检查源文件元素(n.值0);
    Value Ptr = .有解析值!(Value)(n.值0);
    .检查源文件元素(n.值1);
    Value Val = .有解析值!(Value)(n.值1);
    AtomicOrdering_ Ordering = ISK转AtomicOrdering(n.排序);
    if (Ordering == AtomicOrdering_.Unordered && (n.排序 !is ··null!(节点_))) {
        .错误(n.排序, 诊断集_.a0_, "atomicrmw cannot be unordered"d);
    }
    if (!.isPointerTy(Ptr.类型)) {
        .错误(n.值0, 诊断集_.a0_, "atomicrmw operand must be a pointer"d);
    }
    if (!PTy_.s·isOpaqueOrPointeeTypeMatches((cast(指针类型_)(Ptr.类型)), Val.类型)) {
        .错误(n.值0, 诊断集_.a0_, "compare value and pointer type do not match"d);
    }
    if (Operation == AtomicRMWInstBinOp_.Xchg) {
        if (!.isIntegerTy(Val.类型) && !.isFloatingPointTy(Val.类型)) {
            .错误(n.值0, 诊断集_.a0_, "atomicrmw "d ~ "Xchg"d ~ " operand must be an integer or floating point type"d);
        }
    }
    else if (IsFP) {
        if (!.isFloatingPointTy(Val.类型)) {
            .错误(n.值0, 诊断集_.a0_, "atomicrmw "d ~ getAtomicRMWInstBinOpName(n.运算) ~ " operand must be a floating point type"d);
        }
    }
    else {
        if (!.isIntegerTy(Val.类型)) {
            .错误(n.值0, 诊断集_.a0_, "atomicrmw "d ~ getAtomicRMWInstBinOpName(n.运算) ~ " operand must be an integer"d);
        }
    }
    .检查源文件元素(n.同步);
    ubyte SSID = 1;
    if (n.同步 !is ··null!(同步范围设置_)) {
        同步值_ ssid = .有解析值!(同步值_)(n.同步);
        SSID = ssid.Val;
    }
    .检查源文件元素(n.Alignment);
    Align_ Alignment;
    if (n.Alignment !is ··null!(节点_)) {
        Alignment = .有解析值!(对齐值_)(n.Alignment).Val;
    }
    else {
        Alignment = new Align_(DataLayout_.s·getTypeStoreSize(.当前布局, Val.类型).Val);
    }
    bool isVolatile = ((n.isVolatile) !is ··null!(节点_));
    AtomicRMWInst I = InstC_.s·AtomicRMW_C(Operation, Ptr, Val, Alignment, Ordering, SSID, isVolatile);
    .设置解析值(n, I);
}
void 检查栅格指令(栅格指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    AtomicOrdering_ Ordering = ISK转AtomicOrdering(n.排序);
    .检查源文件元素(n.同步);
    ubyte SSID = 1;
    if (n.同步 !is ··null!(同步范围设置_)) {
        同步值_ ssid = .有解析值!(同步值_)(n.同步);
        SSID = ssid.Val;
    }
    if (Ordering == AtomicOrdering_.Unordered) {
        .错误(n.排序, 诊断集_.a0_, "fence cannot be unordered"d);
    }
    if (Ordering == AtomicOrdering_.Monotonic) {
        .错误(n.排序, 诊断集_.a0_, "fence cannot be monotonic"d);
    }
    FenceInst I = InstC_.s·Fence_C(Ordering, SSID);
    .设置解析值(n, I);
}
void 检查获取元素指针指令(获取元素指针指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    bool InBounds = (n.在界内 !is ··null!(节点_));
    .检查源文件元素(n.类型);
    类型_ Ty = .获取类型节点的类型(n.类型);
    .检查源文件元素(n.值0);
    Value Ptr = .有解析值!(Value)(n.值0);
    类型_ BaseType = Ptr.类型;
    指针类型_ BasePointerType = (cast(指针类型_)(.getScalarType(BaseType)));
    if (BasePointerType is ··null!(指针类型_)) {
        .错误(n.值0, 诊断集_.a0_, "base of getelementptr must be a pointer"d);
    }
    if (!PTy_.s·isOpaqueOrPointeeTypeMatches(BasePointerType, Ty)) {
        .错误(n.值0, 诊断集_.a0_, "explicit pointee type doesn't match operand's pointee type"d);
    }
    ElementCount GEPWidth = .isVectorType(BaseType) ? VTy_.s·getElementCount(.cast_!(向量类型_)(BaseType)) : ECFixed(0);
    Value[] Indices = 创建数组!(Value)();
    if ((n.索引组 !is null) && (n.索引组.原型 !is ··null!(值表达式_[]))) {
        {
            for (int i = 0; i < n.索引组.length; ++i) {
                值表达式_ index = n.索引组[i];
                .检查源文件元素(index);
                Value Val = .有解析值!(Value)(index);
                if (!.isIntOrIntVectorTy(Val.类型)) {
                    .错误(index, 诊断集_.a0_, "getelementptr index must be an integer"d);
                }
                向量类型_ ValVTy = .dyn_cast!(向量类型_)(Val.类型);
                if (ValVTy !is ··null!(向量类型_)) {
                    ElementCount ValNumEl = VTy_.s·getElementCount(ValVTy);
                    if (!GEPWidth.p·Op等等(ECFixed(0)) && !GEPWidth.p·Op等等(ValNumEl)) {
                        .错误(index, 诊断集_.a0_, "getelementptr vector index has a wrong number of elements"d);
                        GEPWidth = ValNumEl;
                    }
                }
                .追加!(Value)(Indices, Val);
            }
        }
    }
    if (Indices.length > 0 && !TY_.s·isSized(Ty)) {
        .错误(n, 诊断集_.a0_, "base element of getelementptr must be sized"d);
    }
    if (GEP_.s·getIndexedType(Ty, Indices) is ··null!(类型_)) {
        .错误(n, 诊断集_.a0_, "invalid getelementptr indices"d);
    }
    GetElementPtrInst I = InstC_.s·GetElementPtr_C(Ptr, Indices, InBounds, Ty);
    .设置解析值(n, I);
}
void 检查提取值指令(提取值指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查源文件元素(n.值);
    Value Val = .有解析值!(Value)(n.值);
    if (!.isAggregateType(Val.类型)) {
        .错误(n.值, 诊断集_.a0_, "extractvalue operand must be aggregate type"d);
    }
    uint[] Indices = 创建数组!(uint)();
    if ((n.索引表 !is null) && (n.索引表.原型 !is ··null!(节点_[]))) {
        {
            for (int i = 0; i < n.索引表.length; ++i) {
                节点_ index = n.索引表[i];
                uint idx = (cast(uint)((cast(IR数字字面量_)(index)).整数值));
                .追加!(uint)(Indices, idx);
            }
        }
    }
    类型_ Ty = GEV_.s·getIndexedType(Val.类型, Indices);
    if (Ty is ··null!(类型_)) {
        .错误(n.值, 诊断集_.a0_, "invalid indices for extractvalue"d);
    }
    ExtractValueInst I = InstC_.s·ExtractValue_C(Val, Indices);
    .设置解析值(n, I);
}
void 检查插入值指令(插入值指令_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    .检查源文件元素(n.值0);
    Value Val0 = .有解析值!(Value)(n.值0);
    .检查源文件元素(n.值1);
    Value Val1 = .有解析值!(Value)(n.值1);
    if (!.isAggregateType(Val0.类型)) {
        .错误(n.值0, 诊断集_.a0_, "insertvalue operand must be aggregate type"d);
    }
    uint[] Indices = 创建数组!(uint)();
    if ((n.索引表 !is null) && (n.索引表.原型 !is ··null!(节点_[]))) {
        {
            for (int i = 0; i < n.索引表.length; ++i) {
                节点_ index = n.索引表[i];
                uint idx = (cast(uint)((cast(IR数字字面量_)(index)).整数值));
                .追加!(uint)(Indices, idx);
            }
        }
    }
    类型_ IndexedType = GEV_.s·getIndexedType(Val0.类型, Indices);
    if (IndexedType is ··null!(类型_)) {
        .错误(n.值0, 诊断集_.a0_, "invalid indices for insertvalue"d);
    }
    if (IndexedType != Val1.类型) {
        .错误(n.值1, 诊断集_.a0_, "insertvalue operand and field disagree in type"d);
    }
    ExtractValueInst I = InstC_.s·ExtractValue_C(Val0, Indices);
    .设置解析值(n, I);
}
void 检查指令语句(节点_ n) {
    if (.有解析值!(Value)(n) !is ··null!(Value)) {
        return;
    }
    switch (n.目标种类) {
        case ISK.不及指令: {
            .检查不及指令((cast(不及指令_)(n)));
            break;
        }
        case ISK.返回指令: {
            .检查返回指令((cast(返回指令_)(n)));
            break;
        }
        case ISK.跳转指令: {
            .检查跳转指令((cast(跳转指令_)(n)));
            break;
        }
        case ISK.假如指令: {
            .检查假如指令((cast(假如指令_)(n)));
            break;
        }
        case ISK.直接跳转指令: {
            .检查直接跳转指令((cast(直接跳转指令_)(n)));
            break;
        }
        case ISK.唤出指令: {
            .检查唤出指令((cast(唤出指令_)(n)));
            break;
        }
        case ISK.重启指令: {
            .检查重启指令((cast(重启指令_)(n)));
            break;
        }
        case ISK.清理返回指令: {
            .检查清理返回指令((cast(清理返回指令_)(n)));
            break;
        }
        case ISK.捕获返回指令: {
            .检查捕获返回指令((cast(捕获返回指令_)(n)));
            break;
        }
        case ISK.捕获分支指令: {
            .检查捕获分支指令((cast(捕获分支指令_)(n)));
            break;
        }
        case ISK.清理场指令: {
            .检查清理场指令((cast(清理场指令_)(n)));
            break;
        }
        case ISK.捕获场指令: {
            .检查捕获场指令((cast(捕获场指令_)(n)));
            break;
        }
        case ISK.调用跳转指令: {
            .检查调用跳转指令((cast(调用跳转指令_)(n)));
            break;
        }
        case ISK.取反指令: {
            .检查取反指令((cast(取反指令_)(n)));
            break;
        }
        case ISK.整数和差积及左移指令: {
            .检查整数和差积及左移指令((cast(整数和差积及左移指令_)(n)));
            break;
        }
        case ISK.小数和差积及左移指令: {
            .检查小数和差积及左移指令((cast(小数和差积及左移指令_)(n)));
            break;
        }
        case ISK.有无符号求商及右移指令: {
            .检查有无符号求商及右移指令((cast(有无符号求商及右移指令_)(n)));
            break;
        }
        case ISK.有无符号求余数运算指令: {
            .检查有无符号求余数运算指令((cast(有无符号求余数运算指令_)(n)));
            break;
        }
        case ISK.位运算指令: {
            .检查位运算指令((cast(位运算指令_)(n)));
            break;
        }
        case ISK.比较运算指令: {
            .检查比较运算指令((cast(比较运算指令_)(n)));
            break;
        }
        case ISK.转换类指令: {
            .检查转换类指令((cast(转换类指令_)(n)));
            break;
        }
        case ISK.分配指令: {
            .检查分配指令((cast(分配指令_)(n)));
            break;
        }
        case ISK.储存指令: {
            .检查储存指令((cast(储存指令_)(n)));
            break;
        }
        case ISK.加载指令: {
            .检查加载指令((cast(加载指令_)(n)));
            break;
        }
        case ISK.可变参数指令: {
            .检查可变参数指令((cast(可变参数指令_)(n)));
            break;
        }
        case ISK.提取元素指令: {
            .检查提取元素指令((cast(提取元素指令_)(n)));
            break;
        }
        case ISK.插入元素指令: {
            .检查插入元素指令((cast(插入元素指令_)(n)));
            break;
        }
        case ISK.洗牌向量指令: {
            .检查洗牌向量指令((cast(洗牌向量指令_)(n)));
            break;
        }
        case ISK.PHI节点指令: {
            .检查PHI节点指令((cast(PHI节点指令_)(n)));
            break;
        }
        case ISK.着陆场指令: {
            .检查着陆场指令((cast(着陆场指令_)(n)));
            break;
        }
        case ISK.冻结指令: {
            .检查冻结指令((cast(冻结指令_)(n)));
            break;
        }
        case ISK.调用指令: {
            .检查调用指令((cast(调用指令_)(n)));
            break;
        }
        case ISK.原子修改内存按条件指令: {
            .检查原子修改内存按条件指令((cast(原子修改内存按条件指令_)(n)));
            break;
        }
        case ISK.原子修改内存指令: {
            .检查原子修改内存指令((cast(原子修改内存指令_)(n)));
            break;
        }
        case ISK.栅格指令: {
            .检查栅格指令((cast(栅格指令_)(n)));
            break;
        }
        case ISK.获取元素指针指令: {
            .检查获取元素指针指令((cast(获取元素指针指令_)(n)));
            break;
        }
        case ISK.提取值指令: {
            .检查提取值指令((cast(提取值指令_)(n)));
            break;
        }
        case ISK.插入值指令: {
            .检查插入值指令((cast(插入值指令_)(n)));
            break;
        }
        default: break;
    }
    return;
}
